最近为了实现类的私有方法的单元测试,我使用PrivateObject通过创建私有访问器而不是使用Reflection ,我收到了以下代码审查注释:
“我对私有对象的主要关注是在构造函数中使用object []。它取代了编译器强制执行的强类型操作和JavaScript式运行时错误检测。因此,个人而言,我不推荐它。” p>
上面的评论让我感到困惑,因为根据我的理解,Reflection也需要object[]
来调用任何方法。请帮助我了解最佳方法。
答案 0 :(得分:6)
这在伟大的书重构测试代码http://xunitpatterns.com/
中称为测试特定子类或测试特定扩展您可以在此处阅读有关测试私有方法的更多详细信息和想法:http://xunitpatterns.com/Test-Specific%20Subclass.html
就像
一样public TestClass : RealClass
{
public int CallHiddenCalculate()
{
return Calculate(); // Calculate is now protected method that we expose for test purposes in this class
}
}
您可以将此类放置到测试程序集中,这样您的实际程序集就不会包含特定于测试的逻辑和类,因为它的设计很糟糕。
#if DEBUG public #else private #endif
在Debug中的这种情况下,您可以调用单元测试,但在发布时,这些方法将不可见。 然而,这种方法比上述方法更糟糕,也更丑陋。
只是测试公共接口很容易(通常不是),以便说您获得了良好的测试覆盖率,并且您的代码易于维护和重构。
至于将私有方法标记为内部并且具有测试程序集,请参阅内部方法有很多原因
我认为还有更多但最重要的是
答案 1 :(得分:4)
有趣的问题。通常,单元测试旨在从类的使用者的角度验证类的公共行为。也就是说,只要你的班级信守承诺,消费者就不会在意这么做。
如果您真的需要将“私人”成员公开给单元测试,请将它们标记为内部并通过InternalsVisibleTo属性访问它们。这很难看,但它确实有效,你可以稍后通过一些条件编译将它从程序集中删除。
答案 2 :(得分:2)
你是对的,使用反射与使用PrivateObject模式有很多相同的缺陷。更好的解决方案是避免尝试专门测试私有方法。
答案 3 :(得分:0)
如果您使用的是 Gallio/MbUnit 测试框架,则可以考虑使用内置的Mirror API。
有时,编写测试最明显的方法是访问非公共状态或行为。它可能不是编写测试的最佳方式,但它似乎是目前最简单的解决方案。 MbUnit提供了几个类来帮助访问非公共成员。