【问题标题】:unit testing on public void method which updates private member对更新私有成员的公共 void 方法进行单元测试
【发布时间】:2016-01-01 16:34:33
【问题描述】:
我有下面的公共 void 方法:
public void Reset()
{
// Get updates
// update logic for each value in _dict
}
而 _dict 是类的私有成员:
private readonly dictionary<string, string> _dict;
如何对 Reset() 方法的更新逻辑进行单元测试?重置后如何验证 _dict 中的值是否正确?我不想为 _dict 设置公共 getter 来公开它。
我正在使用 xunit 和 C#。
【问题讨论】:
标签:
c#
unit-testing
xunit
【解决方案1】:
我很粗鲁,所以我认为你应该尝试 TDD,因为它可以有效地防止这样的不可测试的设计。
在您的具体情况下,我们无法获得完整的故事。 Reset() 的效果应该可以从类外部观察到,否则您不需要该方法。
现在我不得不猜测调用Reset() 可能有太多可观察到的效果,所以测试它们会很痛苦。我建议将您的课程分为两类,一类具有“功能”,一类具有“重置”能力。然后,在可重置类上调用 Reset() 的所有效果都是可观察的,您可以对其进行测试,并且不会有其他私有成员在 Reset() 和您还拥有的任何功能之间传递信息的风险。
更新:总是按照 Mark Seemann 告诉你的去做,因为他永远是对的 :)
【解决方案2】:
调用Reset() 应该有一些可观察到的效果,您可以使用类的公共接口进行测试。私有字段和方法是实现细节,你不应该直接测试它们。
编写单元测试的主要目标之一是能够在保持可见行为不变的同时修改实现。如果您测试私有字段或方法,重构将破坏您的测试。一段时间后,您要么完全停止重构,要么会遇到一堆红色测试。
所以问问自己,为什么将public Reset() 方法添加到您的课程中?为什么你班的客户会调用这个方法?
例如,如果您使用私有字典来实现某种缓存并且Reset() 方法会清除缓存,请模拟您的存储库并在调用Reset() 后测试您是否获得了新数据。
如果你找不到一种方法来测试使用你的类的公共接口调用它的效果,那么你不需要这个方法。删除它。更少的代码 = 更容易维护。