C#:使用私有静态成员进行单元测试?

发布于 2024-12-08 00:05:41 字数 598 浏览 2 评论 0原文

我有一个具有如下构造的类:

private static Dictionary<Contract, IPriceHistoryManager> _historyManagers = new Dictionary<Contract, IPriceHistoryManager>();

并且可以说 2 个方法,例如:

 public void AddSth()
 {
    _historManagers.Add(new Contract(), new PriceHistoryManager());
 }

 public int CountDic()
 {
    return _historyManagers.Count(); 
 }

问题: 运行单元测试时,无法“重置”字典,并且当我使用该类的单独实例创建多个单元测试时,“CountDic”会给出不可预测的结果,并且我无法测试监听。

问题: 这通常被认为是一种“坏”方法吗?如果是:如何做得更好/更易于单元测试? 如果不是:如何最好地进行单元测试?

谢谢。

I have a class with a construct like this:

private static Dictionary<Contract, IPriceHistoryManager> _historyManagers = new Dictionary<Contract, IPriceHistoryManager>();

and lets say 2 methods like:

 public void AddSth()
 {
    _historManagers.Add(new Contract(), new PriceHistoryManager());
 }

 public int CountDic()
 {
    return _historyManagers.Count(); 
 }

Problem:
When running unittests there is no way to "reset" the Dictionary and when i create multiple unittests with seperate instances of the class, then "CountDic" gives unpredictable results and i can't test the listentries.

Question:
Is this generally considered a "bad" approach and if yes: how to do it better/more unittestable?
And if not: How to unittest this best?

Thx.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风渺 2024-12-15 00:05:41

不要害怕为了测试目的而暴露公共操作。摘自 Roy Osherove 的《单元测试的艺术》:当丰田制造汽车时,就有可用的测试点。当英特尔制造芯片时,有可用的测试点。汽车或芯片的接口仅用于测试。为什么我们不对软件做同样的事情呢? ResetHistory() 方法会完全破坏您的 API 吗?

如果答案是,则创建该方法,但将该方法设置为内部。然后,您可以使用程序集 InternalsVisibleTo 将内容公开给您的单元测试库。您创建了一个可用于 100% 测试的方法,但您的公共 API 没有任何变化。

Don't be afraid to expose public operations for testing purposes. Paraphrased from "The Art of Unit Testing" by Roy Osherove: When Toyota builds a car, there are testing points available. When Intel builds a chip, there are testing points available. There are interfaces to the car or chip that exist only for testing. Why don't we do the same for software? Would a ResetHistory() method completely destroy your API?

If that answer is yes, then create the method, but make the method internal. You can then use the assembly InternalsVisibleTo to expose the guts to your unit test library. You have a method available to you created 100% for testing, but there's no change to your public API.

要走干脆点 2024-12-15 00:05:41

在您的示例中,CountDic 并不是不可预测的:它应该比调用 AddSth() 之前多返回 1。

所以:

[Test]
public void Test()
{
    var item = new ClassUnderTest();
    int initialCount = item.CountDic();

    item.AddSth();

    int finalCount = item.CountDic();

    Assert.That(finalCount == initialCount + 1);
}

不过,一般来说,测试维护状态的类可能很棘手。有时有必要分解类中维护状态的部分(在您的例子中是字典)并将其移动到另一个类。然后,您可以模拟该“存储”类并通过构造函数将其传递。

In your example, CountDic isn't unpredictable: it should return one more than before the call to AddSth().

So:

[Test]
public void Test()
{
    var item = new ClassUnderTest();
    int initialCount = item.CountDic();

    item.AddSth();

    int finalCount = item.CountDic();

    Assert.That(finalCount == initialCount + 1);
}

In general, though, testing classes that maintain state can be tricky. Sometimes it's necessary to break out the part of the class that maintains state (in your case, the dictionary) and move it to another class. Then, you can mock that "storage" class and pass it in through a constructor.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文