单元测试C#受保护的方法

fis*_*iso 58 .net c# unit-testing protected

我来自Java EE世界,但现在我正在开发一个.Net项目.在Java中,当我想测试受保护的方法时,它非常简单,只需让具有相同包名的测试类就足够了.C#有什么类似的东西吗?单元测试受保护的方法有什么好的做法吗?我只发现框架和人们说我应该只测试公共方法.应该可以在没有任何框架的情况下做到这一点......

非常感谢.

una*_*ity 66

您可以继承要在测试类上测试的类.

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

}
Run Code Online (Sandbox Code Playgroud)

  • **这是错误的答案** 测试类不应该与测试类相同...在很多情况下,测试类需要特殊初始化(fx 它仅在某些容器中有效),并且此解决方案将导致问题 (17认同)
  • 我在单元测试项目中添加了一个'Testable'类扩展类,并使用'TestableMethods'包装所有受保护的方法,并在必要时重新实现匹配的构造函数.相同的结果,但我喜欢将测试与实现分开. (3认同)
  • 感谢您的快速答复。我测试了它的工作原理。我不知道这是否是一个很好的方法,但至少我可以从单元测试开始。 (2认同)
  • @unarity如果我测试的类没有args构造函数(例如,它只有4个args构造函数)怎么办?当我从它派生时,我的测试类将不会编译为“ TestClass不包含接受0个参数的错误的构造函数” (2认同)

Ric*_*ide 25

另一种选择是使用internal这些方法,然后使用InternalsVisibleTo允许测试程序集访问这些方法.这并不会停止同一程序集中的其他类所使用的方法,但它会阻止它们被不是您的测试程序集的其他程序集访问.

这并没有给你那么多的封装和保护,但它非常简单并且非常有用.

添加到AssemblyInfo.cs包含内部方法的程序集中

[assembly: InternalsVisibleTo("TestsAssembly")]
Run Code Online (Sandbox Code Playgroud)

  • “protected”方法对子类(包括程序集外部的子类)可见(并可重写),而“internal”则不然。它们在功能上并不等效,因此此选项仅适用于不需要真正“受保护”方法的情况。 (4认同)
  • @E-Riz如果您希望内部方法可以被程序集外部的子类覆盖,您可以使用受保护的内部https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/protected-internal (受保护的内部和内部都不等同于受保护,但它们在测试时为您提供了不同的选择)。使用子类的最佳答案可能是大多数情况下的最佳解决方案。 (3认同)

typ*_*n04 15

您可以在继承要测试的类的新类中公开受保护的方法.

public class ExposedClassToTest : ClassToTest
{
    public bool ExposedProtectedMethod(int parameter)
    {
        return base.ProtectedMethod(parameter);
    }
}
Run Code Online (Sandbox Code Playgroud)


Jus*_*vey 6

您可以使用反射来调用私有和受保护的方法。

请参阅此处了解更多信息:

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

  • 也许我错了,但我觉得测试需要反思是因为我做错了什么。但如果在 C# 中这很正常,那么我会习惯的。 (18认同)
  • 反射,无论感觉如何,在语义上都是正确的,因为您可以保留方法的可见性,并且不必将方法封装在方法中。 (2认同)

noz*_*zem 6

尽管接受的答案是最好的答案,但它并没有解决我的问题。从受保护的类派生出很多其他东西污染了我的测试类。最后我选择将要测试的逻辑提取到一个公共类中并进行测试。当然,这并不适用于所有人,并且可能需要进行大量重构,但是如果您一直滚动到这个答案,它可能会帮助您。:) 这是一个例子

旧情况:

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

新情况:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)


Usa*_*lam 5

您可以使用PrivateObject类访问所有私有/受保护的方法/字段。

PrivateObject是Microsoft单元测试框架中的一个类,该类是一个包装器,可以调用通常无法访问的成员进行单元测试。

  • 如果它解释了什么是PrivateObject,则此答案将大有裨益。 (12认同)
  • **注意:**这仅在您使用MSTest时适用-不适用于NUnit和XUnit。 (2认同)