我发现自己经常陷入这种模式,我编写了一个由非常小的方法组成的类,这些方法完全由我的单元测试执行。然后我发现我需要构建另一个调用这些方法的方法,我必须为此编写一个更复杂的单元测试——一个简单的例子就可以说明问题:
namespace FooRequest
{
static public class Verifier
{
static public bool IsValid(string request)
{
return (!IsAllCaps(request) && !ContainsTheLetterB(request));
}
static internal bool IsAllCaps(string request)
{
return (request.Equals(request.ToUpper()));
}
static internal bool ContainsTheLetterB(string request)
{
return request.ToLower().Contains("b");
}
}
}
对于代码,我会编写单元测试来涵盖两个内部方法,如下所示:
namespace UnitTest
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FooRequest;
public class VerifierTest
{
[TestClass]
public class ContainsTheLetterB
{
[TestMethod]
public void ShouldReturnTrueForStringContainsB()
{
Assert.IsTrue(Verifier.ContainsTheLetterB("burns"));
}
[TestMethod]
public void ShouldReturnFakseForStringDoesNotContainB()
{
Assert.IsFalse(Verifier.ContainsTheLetterB("urns"));
}
}
[TestClass]
public class IsAllCaps
{
[TestMethod]
public void ShouldReturnTrueForStringIsAllCaps()
{
Assert.IsTrue(Verifier.IsAllCaps("IAMALLCAPS"));
}
[TestMethod]
public void ShouldReturnFakseForStringDoesNotContainB()
{
Assert.IsFalse(Verifier.IsAllCaps("IAMnotALLCAPS"));
}
}
}
}
对于公共方法,我真的只想测试“如果你调用的方法返回 false,则返回 false”——令人讨厌的是,我必须以强制我的内部方法返回 true 或 false 的方式设置输入——我的测试这个方法不应该关心它调用的内部方法(对吗?)
[TestClass]
public class IsValid
{
[TestMethod]
public void ShouldReturnFalseForInvalidStringBecauseContainsB()
{
Assert.IsFalse(Verifier.IsValid("b"));
}
[TestMethod]
public void ShouldReturnFalseForInvalidStringBecauseIsAllCaps()
{
Assert.IsFalse(Verifier.IsValid("CAPS"));
}
[TestMethod]
public void ShouldReturnTrueForValidString()
{
Assert.IsTrue(Verifier.IsValid("Hello"));
}
}
显然,对于这个例子来说,这并不算太糟糕,但是当有很多内部方法并且输入的配置并不简单时,测试我的公共“此输入是否有效”方法会变得复杂。
我应该为所有内部方法创建一个接口,然后将其存根以进行测试,还是有更简洁的方法?