82

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

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

フレームワークなしでそれを行うことが可能であるはずです…</p>

4

8 に答える 8

101

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

[TestClass]
public class Test1 : SomeClass
{
    [TestMethod]
    public void MyTest
    {
        Assert.AreEqual(1, ProtectedMethod());
    }

}
于 2012-11-16T12:04:23.797 に答える
39

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

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

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

[assembly: InternalsVisibleTo("TestsAssembly")]
于 2017-09-12T09:14:42.327 に答える
35

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

public class ExposedClassToTest : ClassToTest
{
    public bool ExposedProtectedMethod(int parameter)
    {
        return base.ProtectedMethod(parameter);
    }
}
于 2017-07-16T08:19:39.817 に答える
8

PrivateObjectクラスを使用して、すべてのプライベート/保護されたメソッド/フィールドにアクセスできます。

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

于 2017-03-06T06:54:14.053 に答える
6

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

詳細については、こちらをご覧ください。

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

于 2012-11-16T12:10:15.970 に答える
6

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

古い状況:

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();
    }
}
于 2018-09-17T12:48:31.653 に答える
0

基本クラスから保護されたメソッドを呼び出すパブリックメソッドを使用してスタブを作成できます。これは、本番環境でこの保護された方法を使用する方法でもあります。

public class FooStub : Bar 
{
    public string MyMethodFoo()
    {
        return MyMethodBar();
    }
}

public abstract class Bar 
{
    protected string MyMethodBar()
    {
        return "Hello World!"
    }
}
于 2021-01-18T12:06:12.673 に答える
0

これが、テストプロジェクトで使用している拡張方法(拡張方法とは何ですか?)です。唯一の欠点は、保護ルールに従い、保護されたメンバーまたはプライベートメンバーを参照できないstringため、文字通り名前をaとして記述する必要があることです。nameof()

        public static MethodInfo GetNonPublicMethod(this Type type, string method)
        {
            MemberInfo[] temp = type.GetMember(method, MemberTypes.Method, BindingFlags.NonPublic | BindingFlags.Instance);
            if (temp.Length == 1)
            {
                if (temp[0] is MethodInfo ret)
                {
                    return ret;
                }
                else
                {
                    throw new ArgumentException("Not a method.");
                }
            }
            else
            {
                if (temp.Length == 0)
                {
                    throw new ArgumentException("Method was not found.");
                }
                else
                {
                    throw new ArgumentException("Multiple methods found.");
                }
            }
        }

この方法の詳細については、https ://docs.microsoft.com/en-us/dotnet/api/system.type.getmember?view=net-5.0をご覧ください。

PS:methodInfo.Invoke(instance, params)それを呼び出すために使用します。

于 2021-09-15T11:34:09.897 に答える