C# で Private メソッドを単体テストするための方法
Privateなメソッドで単体テストを行いたい場合、リフレクションを使う方法、アクセス修飾子を internal に変更する方法があります。
楽だからという理由で全部 Public に変えてしまうのは NG です。公開範囲を適切にコントロールすることがバグを減らすためには必須です。
テスト対象クラス
テストクラス
準備として、Properties 下の AssemblyInfo.cs に以下を追加します(参照したいテスト暮らすの名前空間)。
[assembly: InternalsVisibleTo("UnitTestProject1")]
テスト対象クラス
テストクラス
結論としては、実はリフレクションを使っても、極端にパフォーマンスが悪くなるわけではなかっ
たりします(あまり極端に遅くなったケースは、私は見たことがないです)。
それぞれの現場の思想(好み)にも関係するような話なので、どっちも覚えておくといいですね。
楽だからという理由で全部 Public に変えてしまうのは NG です。公開範囲を適切にコントロールすることがバグを減らすためには必須です。
リフレクションを使った単体テスト
リフレクションを使うため、パフォーマンスはやや劣ります。ただ、既存のコードに手を入れなくてもコードを追加できるメリットがあります。テスト対象クラス
public class Class1 { private string GetHoge(string value) { return value + "Hoge"; } }
テストクラス
[TestClass] public class UnitTest1 { [TestMethod] public void GetHoge_Test() { var value = "ほげ"; var biz = new PrivateObject(new Class1()); var result = biz.Invoke("GetHoge", value); Assert.AreEqual(result.ToString(), value + "Hoge"); } }
internalの単体テスト
対象メソッドの private を internal へ変更します。対象クラスの AssemblyInfo に公開対象にするテストプロジェクトを追加することで、テスト側からも見えるようになります。準備として、Properties 下の AssemblyInfo.cs に以下を追加します(参照したいテスト暮らすの名前空間)。
[assembly: InternalsVisibleTo("UnitTestProject1")]
テスト対象クラス
public class Class1 { internal string GetHoge(string value) { return value + "Hoge"; } }
テストクラス
namespace UnitTestProject1 { [TestClass] public class UnitTest1 { [TestMethod] public void GetHoge_Test() { var value = "ほげ"; var biz = new Class1(); var result = biz .GetHoge(value); Assert.AreEqual(result.ToString(), value + "Hoge"); } } }
結論としては、実はリフレクションを使っても、極端にパフォーマンスが悪くなるわけではなかっ
たりします(あまり極端に遅くなったケースは、私は見たことがないです)。
それぞれの現場の思想(好み)にも関係するような話なので、どっちも覚えておくといいですね。