【问题标题】:C#: Unittesting with private static members?C#:使用私有静态成员进行单元测试?
【发布时间】:2011-10-04 11:54:03
【问题描述】:

我有一个具有这样结构的类:

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”会给出不可预测的结果,我无法测试监听。

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

谢谢。

【问题讨论】:

  • 为什么字典是静态的?
  • 因为它在 WCF 服务中使用,我希望它的多个实例使用它..
  • 静态字典有什么用?
  • 你使用静态字典作为一种缓存?
  • @David 您能否通过创建 ServiceHost 实例并注入共享历史管理器的自定义 ServiceHostFactory 来解决使用它的多个实例的问题,那么您就不需要仅仅为了测试

标签: c# unit-testing static private-members


【解决方案1】:

不要害怕出于测试目的而公开公开操作。从 Roy Osherove 的“单元测试的艺术”中转述:当丰田制造汽车时,有可用的测试点。当英特尔制造芯片时,有可用的测试点。汽车或芯片的接口仅用于测试。为什么我们不对软件做同样的事情? ResetHistory() 方法会完全破坏您的 API 吗?

如果答案是yes,则创建方法,但创建方法internal。然后,您可以使用程序集 InternalsVisibleTo 向您的单元测试库公开内容。您有一个可用的方法创建 100% 用于测试,但您的公共 API 没有变化。

【讨论】:

  • 有时,是的;但在这里我宁愿打破一个持久类,使整体设计更简洁。
  • The Art of Unit Testing 的另一个不错的 qoute 是“当我们为代码编写单元测试时,我们正在向对象模型添加另一个最终用户(测试)。最终用途是与原始测试一样重要,但在使用该模型时它有不同的目标。”(第 77 页)换句话说,测试是您系统的重要用户,它们证明将应用程序的某些部分公开(但是,当然,在编写可重用的类库时,这可能会有所不同)。
  • 我喜欢这个主意,会试一试!
【解决方案2】:

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

所以:

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

    item.AddSth();

    int finalCount = item.CountDic();

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

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

【讨论】:

  • 如果我“连续”有 3 个独立的单元测试,每个都创建自己的类实例和未知数量的“AddSth”调用,那么第二个和第三个单元测试在列表,因为他们不知道也不应该知道彼此......
  • 您所知道的(以及您可以测试的)只是计数的更改——这是对 AddSth() 的调用次数。
  • 是的,但是每个测试都是连续运行的。所以你应该知道你在给定的测试中添加了多少东西。
  • @David:如果您为每个单元测试创​​建一个实例,您需要重新考虑是否真的需要静态字典....并且在每个单元测试上,您只需在调用 AddSth() 之前先获取 CountDic() )。这样你就可以得到初始值来测试......
  • 好的,如果您有 3 个 Test() 方法:Test1()、Test2()、Test3(),您将不再有可预测的结果,因为它们可能由一个实例执行,例如TestRunner.exe 和静态列表条目保留在“testborders”之上,无法重置它们
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-13
  • 2011-10-10
  • 2020-04-30
  • 1970-01-01
  • 1970-01-01
  • 2014-09-02
相关资源
最近更新 更多