假设我有这样的功能:
public void AddEntry(Entry entry)
{
if (entry.Size < 0)
throw new ArgumentException("Entry size must be greater than zero");
DB.Entries.Add(entry);
}
并进行相应的单元测试:
[TestMethod]
[ExpectedException(typeof(ArgumentException), "Entry size must be greater than zero")]
public void AddEntry_TermSizeLessThanZero_ThrowException()
{
Entry e = new Entry(-5);
AddEntry(e);
}
然后我重构了验证码:
public void AddEntry(Entry entry)
{
Validate(entry);
DB.Entries.Add(entry);
}
public void Validate(Entry entry)
{
if (entry.Size < 0)
throw new ArgumentException("Entry size must be greater than zero");
}
单元测试不再描述验证码。
在这种情况下,最好的做法是什么?我是否只是通过AddEntry离开Validate()进行测试?
编辑:澄清一下,假设我有理由将折射代码公开(在这种情况下有点做作),我想复制测试代码是否彻底?
答案 0 :(得分:6)
由于您将Validate()
方法设为对象的公共成员(无论出于何种原因),您当然应该为其添加单独的测试。 AddEntry
的测试应保持不变。
单元测试应仅测试单元的接口,不应假设任何实现细节。因此,在这种情况下,您应该按照原样保留AddEntry
的测试,因为它描述了接口的行为。但是,您不应该假设或测试AddEntry()
来电Validate()
。
答案 1 :(得分:2)
此时我不会向Validate()添加测试,因为该代码已经被现有测试命中。我喜欢这个测试,因为它与班级的要求非常吻合。
当您在类或其他类中的其他函数中开始使用Validate()时,这会发生更改。还可以扩展Validate()以验证不同的问题,您需要解决此问题。
当Validate()有多个调用者,并且Validate()开始测试多个条件时,您可能需要:
似乎以这种方式添加测试可以保持良好的覆盖率,同时根据测试的需求数量线性扩展。
答案 2 :(得分:2)
随着此代码的发展,有两种可能性:
Validate()
保持简单并充当私人助手,外部呼叫者(包括测试)不应该知道。在这种情况下,Validate()
不应该有自己的测试,而是通过调用它的其他方法测试其行为。
Validate()
变得足够复杂,您必须复制大量测试代码,以验证它应该在每个位置调用。在这种情况下,我会考虑提取一个接口+类来执行验证。然后可以在新家中彻底测试Validate()
,并在IValidator
的测试中使用假的AddEntry
(或其他),声明必要时调用Validate()