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

正确的做法是什么?


当前回答

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

但是,有时,在对编译或第三方程序集进行一些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();

其他回答

在极少数情况下,我想要测试私有函数,我通常会将它们修改为受保护的,并且我已经编写了一个带有公共包装器函数的子类。

类:

...

protected void APrivateFunction()
{
    ...
}

...

测试子类:

...

[Test]
public void TestAPrivateFunction()
{
    APrivateFunction();
    //or whatever testing code you want here
}

...

我倾向于不使用编译器指令,因为它们很快就会把事情弄得乱七八糟。如果你真的需要它们,一种缓解它的方法是把它们放在一个partial类中,并让你的构建在制作产品版本时忽略那个.cs文件。

这里有一篇关于私有方法单元测试的好文章。但是我不知道哪个更好,是让你的应用程序专门为测试而设计(就像只为测试而创建测试)还是使用反射来测试。 我敢肯定大多数人都会选择第二种方式。

1)如果你有一个遗留代码,那么测试私有方法的唯一方法就是反射。

2)如果它是新代码,那么你有以下选项:

使用反射(使之复杂) 在同一个类中编写单元测试(使生产代码变得丑陋 其中还包含测试代码) 在某种util类中重构并使方法为公共 使用@VisibleForTesting注释并删除private

I prefer the annotation method, simplest and least complicated. The only issue is that we have increased the visibility which I think is not a big concern. We should always be coding to interface, so if we have an interface MyService and an implementation MyServiceImpl then we can have the corresponding test classes that is MyServiceTest (test interface methods) and MyServiceImplTest (test private methods). All clients should anyway be using the interface so in a way even though the visibility of the private method has been increased it should not really matter.

在我看来,你应该只对类的公共API进行单元测试。

为了对方法进行单元测试,将其设为公共,会破坏封装,暴露实现细节。

一个好的公共API解决了客户端代码的直接目标,并且完全解决了这个目标。