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