在阅读了一篇
blog post,提到为了便于测试而揭露公共吸气剂似乎是错误的,我找不到任何更好的做法的具体例子.
假设我们有这个简单的例子:
public class ProductNameList { private IList<string> _products; public void AddProductName(string productName) { _products.Add(productName); } }
让我们说出于面向对象设计的原因,我没有必要公开公开产品列表.那么我怎样才能测试AddProductName()是否完成了它的工作? (也许它添加了两次产品,或者根本没有.)
一种解决方案是公开_products的只读版本,我可以测试它是否只有一个产品名称 – 我传递给AddProductName()的产品名称.
我之前提到的博客文章说它更多的是关于交互(即产品名称是否被添加)而不是状态.然而,状态正是我正在检查的.我已经知道AddProductName()已被调用 – 我想测试该方法完成其工作后对象的状态是否正确.
免责声明:虽然这个问题类似于
Balancing Design Principles: Unit Testing,(1)语言不同(C#而不是Java),(2)这个问题有示例代码,(3)我觉得问题没有得到充分的回答(即代码会帮助证明这个概念) .
解决方法
你可以使你的访问者受到保护,这样你就可以模拟或者你可以使用内部,这样你就可以在测试中访问该属性,但是IMO会像你建议的那样错误.
我想有时我们会陷入困境,希望确保我们的代码中的每一件小事都经过测试.有时我们需要退后一步,问我们为什么要存储这个值,它的目的是什么?然后,我们可以开始测试组件的行为是否正确,而不是测试值是否已设置.
编辑
在你的场景中你可以做的一件事是有一个混蛋构造函数,你注入一个IList然后你测试你已经添加了一个产品:
public class ProductNameList { private IList<string> _products; internal ProductNameList(IList<string> products) { _products = products; } ... }
然后你会像这样测试它:
[Test] public void FooTest() { var productList = new List<string>(); var productNameList = new ProductNameList(productList); productNameList.AddProductName("Foo"); Assert.IsTrue(productList[0] == "Foo"); }
您需要记住使内部对您的测试组件可见.