C#中的单元测试私有方法

C#中的单元测试私有方法

问题描述:

Visual Studio 允许通过自动生成的访问器类对私有方法进行单元测试.我编写了一个私有方法的测试,该方法编译成功,但在运行时失败.代码和测试的一个相当小的版本是:

Visual Studio allows unit testing of private methods via an automatically generated accessor class. I have written a test of a private method that compiles successfully, but it fails at runtime. A fairly minimal version of the code and the test is:

//in project MyProj
class TypeA
{
    private List<TypeB> myList = new List<TypeB>();

    private class TypeB
    {
        public TypeB()
        {
        }
    }

    public TypeA()
    {
    }

    private void MyFunc()
    {
        //processing of myList that changes state of instance
    }
}    

//in project TestMyProj           
public void MyFuncTest()
{
    TypeA_Accessor target = new TypeA_Accessor();
    //following line is the one that throws exception
    target.myList.Add(new TypeA_Accessor.TypeB());
    target.MyFunc();

    //check changed state of target
}

运行时错误是:

Object of type System.Collections.Generic.List`1[MyProj.TypeA.TypeA_Accessor+TypeB]' cannot be converted to type 'System.Collections.Generic.List`1[MyProj.TypeA.TypeA+TypeB]'.

根据智能感知 - 因此我猜编译器 - 目标是 TypeA_Accessor 类型.但是在运行时它是 TypeA 类型,因此列表添加失败.

According to intellisense - and hence I guess the compiler - target is of type TypeA_Accessor. But at runtime it is of type TypeA, and hence the list add fails.

有什么办法可以阻止这个错误?或者,也许更有可能的是,其他人有什么其他建议(我预测可能不要测试私有方法"和不要进行单元测试来操纵对象的状态").

Is there any way I can stop this error? Or, perhaps more likely, what other advice do other people have (I predict maybe "don't test private methods" and "don't have unit tests manipulate the state of objects").

您可以使用 PrivateObject 类:

You can use the PrivateObject class:

Class target = new Class();
PrivateObject obj = new PrivateObject(target);
var retVal = obj.Invoke("PrivateMethod");
Assert.AreEqual(expectedVal, retVal);

注意:PrivateObjectPrivateType 不适用于面向 netcoreapp2.0 的项目 - GitHub 问题 366

Note: PrivateObject and PrivateType are not available for projects targeting netcoreapp2.0 - GitHub Issue 366