我发现自己经常陷入这种模式中,我编写了一个由非常小的方法组成的类,这些方法完全由我的单元测试覆盖。然后我发现我需要构建另一个调用这些方法的方法,我必须为此编写一个更复杂的单元测试 - 一个简单的例子会很有说明性:
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"));
}
}
很明显,对于这个例子来说,情况还不错,但是当有很多内部方法且输入难以配置时,测试我的公共“输入是否有效”方法就变得复杂了。
我应该为所有的内部方法创建一个接口,然后在测试中将其存根化,还是有更简洁的方式?