Unit testing 如何在BDD/TDD中对私有方法进行单元测试?
我试图根据行为驱动的发展来编程, 其中规定,任何一行代码都不应在未编写的情况下编写 首先是单元测试失败 我的问题是,如何将BDD与私有方法一起使用Unit testing 如何在BDD/TDD中对私有方法进行单元测试?,unit-testing,tdd,bdd,Unit Testing,Tdd,Bdd,我试图根据行为驱动的发展来编程, 其中规定,任何一行代码都不应在未编写的情况下编写 首先是单元测试失败 我的问题是,如何将BDD与私有方法一起使用 如何对私有方法进行单元测试 有比:更好的解决方案吗 -先公开私有方法,然后将其私有化 当我编写使用这些私有方法的公共方法时 或 -在C#中,将所有私有方法设置为内部方法,并使用InternalsVisibleTo 属性 如果存在私有方法,则它将被公共方法使用。因此,我将为public方法编写一个测试 我编写测试是为了测试类的公共部分。如果类设计良好,
如何对私有方法进行单元测试
有比:
更好的解决方案吗 -先公开私有方法,然后将其私有化 当我编写使用这些私有方法的公共方法时
或
-在C#中,将所有私有方法设置为内部方法,并使用InternalsVisibleTo 属性
如果存在私有方法,则它将被公共方法使用。因此,我将为public方法编写一个测试 我编写测试是为了测试类的公共部分。如果类设计良好,则默认情况下会测试私有部分 如果私有方法不是从公共方法调用的,那么它为什么存在呢 就你的情况而言,我会做以下几点
* Write failing test for the public method
* Write public method that calls the private method that doesn't exist yet(test still fails as your class is incomplete
* Write the private method
* Test should now pass
私有方法是内部实现细节。不应该直接测试它们,因为它们将通过测试公共接口进行间接测试。如果由于某种原因,在对公共接口进行完全测试时未涵盖私有方法,则不需要该私有方法,应将其删除
通常,将测试代码绑定到私有实现细节是个坏主意。这会将您的测试与那些私人细节结合起来,减少您随意更改这些细节的自由,即使它们不会影响面向公众的界面和行为。这增加了编写和维护单元测试所需的工作量,这是一件消极的事情。您应该尽可能多地覆盖,同时只绑定到公共接口。当您首先编写代码测试时,您是针对公共接口编写的。此时没有私有方法 然后编写代码以通过测试。如果这些代码中的任何一个被分解到私有方法中,那并不重要——它应该仍然存在,因为它被公共接口使用
如果代码不是首先通过测试编写的,那么——无论如何,在.net中——可以使用反射直接生成私有方法;尽管这是最后的手段。您应该只测试类的外部API,即公共方法。如果您的测试没有命中私有方法中的代码,那么您需要编写更多的测试或重构类 测试API(尤其是将分发给第三方的API)的全部要点是,只要不破坏类的公共方法的外部契约,就可以随意更改类的内部结构
正如您所确定的,这是BDD比使用模拟类的“传统”TDD发挥作用的地方,在模拟类中,每个方法调用都必须为测试提前设置。我不是这两方面的专家,希望其他人能比我更好地回答这个问题。简短回答:你不测试私有方法。
如果编程良好,测试的代码覆盖率应该是隐式测试私有方法。我同意关于不测试私有方法本身的观点,测试应该针对公共API编写,但上面没有列出另一个选项 您可以使这些方法受到保护,然后从被测试的类派生。您可以在派生类上使用公共方法公开受基保护的方法,例如
public class TestableClassToTest : ClassToTest
{
public new void MethodToTest()
{
base.MethodToTest();
}
}
您可能已经在使用此提取和重写模式来重写基类的虚拟属性以进行依赖项注入,在这种情况下,这可能是一个可行的选项。简短回答:您无法测试私有方法 <>强>长回答< /强>:您不能测试私有方法,但是如果您倾向于测试它所做的任何事情,请考虑重构您的代码。有两种简单的方法:
- 测试访问私有方法的公共方法
- 将私有代码提取到它自己的类中,即移动实现以便它可以适当地公开
如果您正在为已部署的类编写测试,则可以调查调用私有方法的所有内容,并相应地编写测试。如果你有机会重写这个类,那么请通过拆分这个类来重构它。如果幸运的话,您最终会得到一些可以利用的代码重用。Mbunit Reflector可以帮助您做到这一点
Reflector objectReflection = new Reflector(new ObjectWithprivateMethods());
objectReflection.InvokeMethod(AccessModifier.NonPublic,,"Add",1,6));
如果您发现自己想要测试一个私有方法,那么其中有一些复杂的东西,您想要测试它可能是正确的,这是一种设计的味道。在接口上暴露方法只会将一种气味换成另一种更糟糕的气味 重构时间:) 通常我会将内部复杂性分解成一个helper类。然而,检查“特征嫉妒”或“不适当亲密”的方法。也许有一个更好的地方适合这种方法居住。现在使用.net中的扩展方法,即使是基类型也可以
var objectOfPrivateMethod = new ObjectOfPrivateMethod(); //yes here is contructor
object[] arguments = { }; // here as Object you provide arguments
var extractedPrivateMethod = typeof(ObjectOfPrivateMethod).GetMethod("Name_Of_Private_Method", BindingFlags.NonPublic|BindingFlags.Static); //if fails returns null. delete flag static if it's not static. Returns your method as an object.
Assert.AreNotEqual(null, extractedPrivateMethod, "Mathod does not exist"); // good to catch if even exists.
object result = extractedPrivateMethod.Invoke(null, arguments); // here as object you'll get return value of your function. change null for object of class where is method, if your method is not static