简体   繁体   English

单元测试 C# 保护方法

[英]Unit testing C# protected methods

I come from the Java EE world but now I'm working on a .Net project.我来自 Java EE 世界,但现在我正在从事一个 .Net 项目。 In Java when I wanted to test a protected method it was quite easy, just having the test class with the same package name was enough.在 Java 中,当我想测试一个受保护的方法时,这很容易,只要让测试类具有相同的包名就足够了。

Is there anything similar for C#? C# 有类似的东西吗? Is there any good practice for unit testing the protected methods?对受保护的方法进行单元测试有什么好的做法吗? I only found frameworks and people saying that I should test only public methods.我只发现框架和人们说我应该只测试公共方法。

It should be possible to do it without any framework…应该可以在没有任何框架的情况下做到这一点......

You can inherit the class you are testing on your test class.您可以在测试类上继承正在测试的类。

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

}

Another option is to use internal for these methods and then use InternalsVisibleTo to allow your test assembly to access these methods.另一种选择是对这些方法使用internal ,然后使用InternalsVisibleTo允许您的测试程序集访问这些方法。 This does not stop the methods being consumed by other classes in the same assembly, but it does stop them being accessed by other assembles that are not your test assembly.这不会阻止同一程序集中其他类使用的方法,但会阻止不是您的测试程序集的其他程序集访问它们。

This does not give you as much encapsulation and protection but it's pretty straight forward and can be useful.这不会为您提供尽可能多的封装和保护,但它非常直接并且很有用。

Add to AssemblyInfo.cs in the assembly containing the internal methods在包含内部方法的程序集中添加到AssemblyInfo.cs

[assembly: InternalsVisibleTo("TestsAssembly")]

You can expose the protected methods in a new class that inherits the class you want to test.您可以在继承要测试的类的新类中公开受保护的方法。

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

You can use PrivateObject class to access all the private/ protected methods/ fields.您可以使用 PrivateObject 类访问所有私有/受保护的方法/字段。

PrivateObject is a class in the Microsoft unit testing framework which is a wrapper that enables calling normally inaccessible members for unit testing. PrivateObject 是 Microsoft 单元测试框架中的一个类,它是一个包装器,可以调用通常无法访问的成员进行单元测试。

Although the accepted answer is the best one, it didn't solve my problem.尽管接受的答案是最好的答案,但它并没有解决我的问题。 Deriving from the protected class polluted my test class with a lot of other stuff.从受保护的类派生出很多其他东西污染了我的测试类。 In the end I chose to extract the to-be-tested-logic into a public class and test that.最后我选择将要测试的逻辑提取到一个公共类中并进行测试。 Surely enough this will not work for everyone and might require quite some refactoring, but if you scrolled all the way up to this answer, it might just help you out.当然,这并不适用于所有人,并且可能需要进行大量重构,但是如果您一直滚动到这个答案,它可能会帮助您。 :) Here's an example :) 这是一个例子

Old situation:旧情况:

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

New situation:新情况:

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();
    }
}

You can use reflection to invoke private and protected methods.您可以使用反射来调用私有和受保护的方法。

See here for more:请参阅此处了解更多信息:

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

You can create a stub with a public method that calls the protected method from the base class.您可以使用从基类调用受保护方法的公共方法创建存根。 This is also how you would use this protected method in production.这也是您在生产中使用这种受保护方法的方式。

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

public abstract class Bar 
{
    protected string MyMethodBar()
    {
        return "Hello World!"
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM