私は自分がこのパターンにかなり陥っていることに気づきました。単体テストによって完全に実行される非常に小さなメソッドで構成されるクラスを作成します。次に、これらのメソッドを呼び出す別のメソッドを作成する必要があることがわかり、そのためのより複雑な単体テストを作成する必要があります。簡単な例がわかりやすいでしょう。
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");
}
}
}
コードについては、次のような 2 つの内部メソッドをカバーする単体テストを作成します。
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"));
}
}
この例では明らかに悪いことではありませんが、多くの内部メソッドがあり、入力を構成するのが簡単ではない場合、公開されている「Is This Input Valid」メソッドのテストが複雑になります。
すべての内部メソッドのインターフェイスを作成してから、テスト用にスタブ化する必要がありますか、それともより適切な方法がありますか?