关于c#:如何围绕私有方法编写单元测试

How to write unit tests around private methods

我正在尝试对具有公共和私有方法的类进行单元测试,并且我想对已设置为私有的特定方法(基础上的受保护抽象)进行单元测试。我不能使方法公开,我不想通过完整的过程来测试这个方法,我只关心这个方法的输入参数和返回满足期望。

这个问题强调我不想公开这个方法:

公开私有方法对其进行单元测试......好主意?

我的问题是,测试私有方法的各种方法有哪些,我应该采用哪种技术?为什么?

我已经阅读了这个问题(你如何对私人方法进行单元测试?)但是想知道接受的答案是否仍然是最好的答案,或者在几年后有更好的方法。

如果这个问题被认为是重复的,你如何对私有方法进行单元测试?我会在那里添加我的评论并要求更新,请指教。


如果你不能通过公共方法有意义地测试类的私有方法,那么这将表明类的设计有问题。如果很难测试该类,以便您希望分解测试以测试其功能的子集,那么我建议将该类分解为逻辑部分并单独测试它们。

也许您有机会重构代码,以便私有方法成为其他类的公共方法。一个很好的例子是一个类,它安排一些计时器的工作,以便稍后处理。工作方法可能会被实现为私有方法,这使得难以在不调度计时器的情况下以简单的方式进行测试,并等待它执行工作方法。在执行时间非常快的测试中并不理想。解决此问题的一个简单方法是将调度工作代码拆分为两个单独的类。私有工作方法然后成为Worker类的公共方法,使其非常容易测试。虽然拆分调度和工作代码意味着您将难以实现100%的覆盖率,但您至少会覆盖工作代码。解决这个问题的方法是使用Quartz.net之类的东西来实现调度程序类,这样你就可以很容易地对调度程序和工作程序代码进行单元测试。


I have read this question (How do you unit test private methods?) but
would like to know if the accepted answer is still the best answer or
after years there is a better way.

我会避免接受的答案。

我可以跳进关于测试公共接口的长篇大论,而不是担心内部,但这可能不太现实。

我可以看到两个直接选项:

  • 反思看看这种方法,有点像黑客,但至少你可以得到某种测试。这也可能是最容易快速工作的。
  • 使用类似策略模式的东西抽象私有方法行为,并将行为注入对象本身(或者让对象在内部new手动提升相关策略)。然后可以独立地测试该单独的策略项目。

也就是说,你不应该经常发现自己处于这种状况。如果你这样做,你需要退后一步,检查你如何设计你的类,并可能审查它们,以使它们更开放和可测试。


您是否希望能够在测试中调用您的私有方法并查看它是如何工作的?

您可以从您的类派生并添加将调用您要测试的方法的公共方法。非常简单。虽然我不建议测试私有方法。我想不出单一的理由去做。我很乐意看到会改变主意的例子。


在VS 2005,2008和2010中,您可能拥有私人访问者。右键单击私有函数,然后选择"创建私有访问者"...

在VS 2012中,这个功能已经不见了。唯一方便的方法是使用PrivateObject。您可以查看MSDN以获取使用PrivateObject的示例。


我实际来到这里是为了回答这个问题,直到我意识到我不应该对私人方法进行单元测试。这样做的原因是因为私有方法是一个过程中的一部分,它是一些更大逻辑的一部分。

单元测试旨在测试类的接口。我的想法是,当我按照预期的方式使用我的班级时,我应该确保质量控制。因此,单独测试私有方法没有用,只是因为它永远不会暴露给消费者(无论是谁实现)。您需要针对消费者可以使用您的课程的案例进行单元测试。

如果您发现自己绝对需要对某些私有内容进行单元测试,则可能需要重新考虑该方法的位置,或者您的代码如何分解。我得出的结论是,如果我需要对一个私有方法进行单元测试,那么9/10次它就是一个可以包装到静态实用程序类中的方法。


如果您使用的是VS 2005或更高版本,请使用以下步骤

  • 打开包含私有方法的源代码文件。
  • 右键单击私有方法,然后选择"创建单元测试"。
    这将显示"创建单元测试"对话框。在可见树结构中,仅选中私有方法的复选框。
  • (可选)在"创建单元测试"对话框中,可以更改"输出"项目。您还可以单击"设置"以重新配置生成单元测试的方式。
  • 单击
    这将创建一个名为VSCodeGenAccessors的新文件,该文件包含特殊的访问器方法,用于检索正在测试的类中的私有实体的值。您可以在测试项目文件夹中看到解决方案资源管理器中显示的新文件。
    如果您的测试项目在此之前没有进行单元测试,则还会创建一个用于容纳单元测试的源代码文件。与包含私有访问器的文件一样,包含单元测试的文件也在解决方案资源管理器中的测试项目中可见。
  • 打开包含单元测试的文件,然后滚动到私有方法的测试。找到标有// TODO:comments的语句,并按照注释中的说明完成它们。这有助于测试产生更准确的结果
  • 有关更多信息,请参阅此

    它看起来在内部使用反射来调用私有方法。但它的确有效。


    使用反射。如果您不想自己弄乱反射,那么您可以使用位于Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll中的Microsoft的PrivateObject类。但是合作MSTest和NUnit存在问题 - 同时使用MSTest和NUnit?