我正在构建一个类库,它将有一些公共和私有方法。我希望能够对私有方法进行单元测试(主要是在开发过程中,但也可以用于将来的重构)。

正确的做法是什么?


当前回答

我还使用了InternalsVisibleToAttribute方法。值得一提的是,如果你为了达到这个目的而将你之前的私有方法变成内部方法,那么也许它们不应该成为直接单元测试的对象。

毕竟,您是在测试类的行为,而不是它的具体实现——您可以在不更改前者的情况下更改后者,并且您的测试仍然应该通过。

其他回答

如果你正在使用。net,你应该使用InternalsVisibleToAttribute。

测试私有方法可能没有用处。然而,我有时也喜欢从测试方法调用私有方法。大多数时候为了防止代码重复用于测试数据生成…

微软为此提供了两种机制:

访问器

转到类定义的源代码 右键单击类名 选择“创建私有访问器” 选择要在其中创建访问器的项目 你将得到一个名为foo_accessor的新类。 该类将在编译期间动态生成,并提供所有公共成员。

然而,当涉及到原始类的接口更改时,该机制有时有点棘手。所以,大多数时候我避免使用这个。

PrivateObject类 另一种方法是使用microsoft。visualstudio。testtools。unittest。privateobject

// Wrap an already existing instance
PrivateObject accessor = new PrivateObject( objectInstanceToBeWrapped );

// Retrieve a private field
MyReturnType accessiblePrivateField = (MyReturnType) accessor.GetField( "privateFieldName" );

// Call a private method
accessor.Invoke( "PrivateMethodName", new Object[] {/* ... */} );

将它们声明为内部的,然后使用InternalsVisibleToAttribute允许单元测试程序集看到它们。

由于某些原因,私有类型、内部变量和私有成员是这样的,通常你不想直接打乱它们。如果您这样做了,很可能稍后会崩溃,因为不能保证创建这些程序集的人会保留私有/内部实现。

但是,有时,在对编译或第三方程序集进行一些hack /探索时,我自己最终想要初始化一个私有类或具有私有或内部构造函数的类。或者,有时,在处理无法更改的预编译遗留库时——我最终会针对私有方法编写一些测试。

因此诞生了AccessPrivateWrapper - http://amazedsaint.blogspot.com/2010/05/accessprivatewrapper-c-40-dynamic.html -它是一个快速的包装类,使用c# 4.0的动态特性和反射可以使工作变得容易。

您可以创建内部/私有类型,例如

    //Note that the wrapper is dynamic
    dynamic wrapper = AccessPrivateWrapper.FromType
        (typeof(SomeKnownClass).Assembly,"ClassWithPrivateConstructor");

    //Access the private members
    wrapper.PrivateMethodInPrivateClass();

我很惊讶还没有人说过这一点,但我采用的一个解决方案是在类内部创建一个静态方法来测试自身。这使您可以访问用于测试的所有公共和私有内容。

此外,在脚本语言(具有OO功能,如Python、Ruby和PHP)中,您可以在运行时对文件本身进行测试。确保您的更改不会破坏任何东西的快速方法。这显然为测试所有类提供了可伸缩的解决方案:只需运行所有类即可。(你也可以用void main在其他语言中这样做,它也总是运行它的测试)。