C#:使用私有静态成员进行单元测试?
我有一个具有如下构造的类:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不要害怕为了测试目的而暴露公共操作。摘自 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 methodinternal
. You can then use the assemblyInternalsVisibleTo
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.在您的示例中,
CountDic
并不是不可预测的:它应该比调用AddSth()
之前多返回 1。所以:
不过,一般来说,测试维护状态的类可能很棘手。有时有必要分解类中维护状态的部分(在您的例子中是字典)并将其移动到另一个类。然后,您可以模拟该“存储”类并通过构造函数将其传递。
In your example,
CountDic
isn't unpredictable: it should return one more than before the call toAddSth()
.So:
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.