web-dev-qa-db-ja.com

C#で保護されたメソッドの単体テスト

私はJava EEの世界から来ましたが、現在は.Netプロジェクトに取り組んでいます。 Javaで保護されたメソッドをテストしたい場合、それは非常に簡単で、同じパッケージ名のテストクラスがあれば十分でした。

C#に類似したものはありますか?保護されたメソッドの単体テストに良い方法はありますか?私は、パブリックメソッドのみをテストする必要があると言っているフレームワークと人々を見つけました。

フレームワークなしで実行できるはずです…

57
fiso

テストクラスでテストしているクラスを継承できます。

public class Test1 : SomeClass
{
    Asert.AreEqual(1, SomeClass.ProtectedMethod());
}
66
unarity

別のオプションは、これらのメソッドにinternalを使用してから InternalsVisibleTo を使用して、テストアセンブリがこれらのメソッドにアクセスできるようにすることです。これにより、同じアセンブリ内の他のクラスが使用するメソッドは停止しませんが、テストアセンブリではない他のアセンブルがアクセスするメソッドは停止します。

これは、それほど多くのカプセル化と保護を提供しませんが、非常に簡単で便利です。

内部メソッドを含むアセンブリのAssemblyInfo.csに追加します

[Assembly: InternalsVisibleTo("TestsAssembly")]
23
Richard Garside

テストするクラスを継承する新しいクラスで保護されたメソッドを公開できます。

public class ExposedClassToTest : ClassToTest
{
    public bool ExposedProtectedMethod(int parameter)
    {
        return base.ProtectedMethod(parameter);
    }
}
12
typhon04

PrivateObjectクラスを使用して、すべてのprivate/protectedメソッド/フィールドにアクセスできます。

PrivateObjectは、単体テスト用に通常はアクセスできないメンバーを呼び出すことを可能にするラッパーであるMicrosoft単体テストフレームワークのクラスです。

5
Usama Aslam

リフレクションを使用して、プライベートおよび保護されたメソッドを呼び出すことができます。

詳細はこちらをご覧ください:

http://msdn.Microsoft.com/en-us/library/66btctbe.aspx

3
Justin Harvey

受け入れられた答えは最高のものですが、それは私の問題を解決しませんでした。保護されたクラスから派生すると、テストクラスが他の多くのもので汚染されました。最終的に、テスト対象のロジックをパブリッククラスに抽出してテストすることにしました。確かにこれはすべての人にとってうまくいくわけではなく、かなりのリファクタリングが必要になるかもしれませんが、この答えまでずっとスクロールすると、助けになるかもしれません。 :)ここに例があります

以前の状況:

protected class ProtectedClass{
   protected void ProtectedMethod(){
      //logic you wanted to test but can't :(
   }
}

新しい状況:

protected class ProtectedClass{
   private INewPublicClass _newPublicClass;

   public ProtectedClass(INewPublicClass newPublicClass) {
      _newPublicClass = newPublicClass;
   }

   protected void ProtectedMethod(){
      //the logic you wanted to test has been moved to another class
      _newPublicClass.DoStuff();
   }
}

public class NewPublicClass : INewPublicClass
{
   public void DoStuff() {
      //this logic can be tested!
   }
}

public class NewPublicClassTest
{
    NewPublicClass _target;
    public void DoStuff_WithoutInput_ShouldSucceed() {
        //Arrange test and call the method with the logic you want to test
        _target.DoStuff();
    }
}
2
nozem