[コラム] [Visual Studio] 抽象クラスの private メソッドを単体テストするには
※ 初出: biac の それさえもおそらくは幸せな日々@nifty, 2008年5月2日
Visual Studio では、 プライベートメソッドに対しても、 ユニットテストのスケルトンコードを自動生成してくれます。 プライベートメソッドを持つクラスに対するアクセッサークラスを、 自動的に作ってくれるわけです。 そして、 ユニットテスト側では、 この自動生成されたアクセッサークラスを使って、 テストを書きます。
それを踏まえて…
では、 テスト対象のメソッドが、 抽象クラスに含まれているときはどうすればいいでしょう?
こんなテスト対象のクラス AbstractClass1 があったとします。
namespace 抽象クラス {
internal abstract class AbstractClass1 {
protected int _num;
internal AbstractClass1() {
this._num = 1;
}
protected abstract bool foo(int n);
private bool bar(int n) {
return (this._num == n);
}
}
}
さて、 この private なメソッド bar() を、 Visual Studio 2008 のユニットテスト機能で、 直接テスト出来るでしょうか?
※ 通常は、 private メソッドを呼び出している protected 以上のメソッドが必ず存在しますから、 そこをテストすることで間接的に private メソッドをテストできます。 その手法では、 対象メソッドが複雑すぎてやってられない、 というとき、 private メソッドを直接テストしたくなるわけです。
まず、 いくらなんでも抽象クラスだけではインスタンス化できませんから、 どうしても実装クラスは必要です。 AbstractClass1 を継承したクラス ConcreteClass1 を、 ユニットテストのためだけに実装します。
namespace 抽象クラス {
#if UNIT_TEST
internal class ConcreteClass1 : AbstractClass1 {
protected override bool foo(int n) {
return (base._num != n);
}
}
#endif
}
この ConcreteClass1 に対して、 単体テストウィザードでテストコードを自動生成させれば、 ConcreteClass1 の方に実装されている protected メソッド foo() はテストできます。
でも、 それで自動生成された ConcreteClass1_Accessor クラスを使って、 親クラスの private メソッド bar() をテストしようとしても、 出来ません。 ConcreteClass1 から、 継承元のプライベートメソッドは見えませんからね。
そこで、 こんな風にしてユニットテスト側で AbstractClass1 のアクセッサークラスを作ってやると、 bar() もテストできるようになります。
[TestMethod()]
[DeploymentItem("抽象クラス.dll")]
public void barTest()
{
// 実装クラスのインスタンスから、
// 抽象クラス (親) の Accessor を生成する。
PrivateObject po = new PrivateObject(
new ConcreteClass1(),
new PrivateType(typeof(AbstractClass1))
);
AbstractClass1_Accessor target
= new AbstractClass1_Accessor(po);
// 親クラスの実装 private bar() をテスト
Assert.IsFalse(target.bar(0));
Assert.IsTrue(target.bar(1));
// 子クラスの実装 protected foo() も見える
Assert.IsTrue(target.foo(0));
Assert.IsFalse(target.foo(1));
}
| 固定リンク
「*コラム」カテゴリの記事
- [TDD Advent Calendar jp: 2011] TDD とアジャイルを支えるバックボーン #TddAdventJp(2011.12.25)
- [コラム] TDD の原点 ~ Kent Beck による定義(2011.12.13)
- [コラム] TDD は止めて、 DbE (例示による設計) と呼ぼう!(2011.11.03)
- [コラム] NUnit の CollectionAssert で、 配列やリストを比較・検証する(2011.10.31)
- [コラム] TDDBC 東京 1.6 のお題を C# でやってみる (その3) ~ 2つめ、3つめの仕様変更[T16MAIN-6,7](2011.08.30)

コメント