我正在测试一个带有多个参数的函数,并根据它们的值调用不同的私有方法。
我想检查该函数是否始终调用正确的私有方法。
因为我知道私有方法会做什么,所以我可以检查最终结果,但是直接检查是否调用了正确的函数会更方便,因为我已经测试了私有方法。
有没有办法用存根替换 privae 方法?
我正在测试一个带有多个参数的函数,并根据它们的值调用不同的私有方法。
我想检查该函数是否始终调用正确的私有方法。
因为我知道私有方法会做什么,所以我可以检查最终结果,但是直接检查是否调用了正确的函数会更方便,因为我已经测试了私有方法。
有没有办法用存根替换 privae 方法?
是的,有一些模拟库可以让你做到这一点。一个是PowerMock。从他们的私有方法教程中,你需要这样的东西:
@RunWith(PowerMockRunner.class)
@PrepareForTest(MyUnit.class)
public class TestMyUnit {
@Test
public void testSomething() {
MyUnit unit = PowerMock.createPartialMock(MyUnit.class, "methodNameToStub");
PowerMock.expectPrivate(unit, "methodNameToStub", param1).andReturn(retVal);
EasyMock.replay(unit);
unit.publicMethod(param1);
EasyMock.verify(unit);
}
}
但是,我自己真的不同意这种做法。您的单元测试应该测试输入、输出和副作用,仅此而已。通过确保正确调用私有方法,您所做的就是防止您的代码被轻易重构。
换句话说,如果你想改变你的单位的工作方式怎么办?执行此操作的安全方法是确保代码处于(通过)测试中,然后重构代码(可能包括更改调用的内部方法),然后再次运行测试以确保您没有破坏任何东西。使用您的方法,这是不可能的,因为您的测试测试的是确切的实现,而不是单元本身的行为。重构几乎总是会破坏测试,那么测试到底能给你带来多少好处呢?
大多数情况下,您会想要这样做,因为您实际上将这些私有视为自己的一个单元(这听起来像您,因为您说您已经直接测试了这些私有方法!)。如果是这种情况,最好将该逻辑提取到它自己的类中,对其进行测试,然后在剩余的代码中与该新单元的模拟/存根版本进行交互。如果你这样做了,你的代码就会有更好的结构,而且你不需要依赖 PowerMock 的巫术魔法。进行此类重构的绝佳参考是 Michael Feathers 的Working Effectively with Legacy Code。
如果调用正确的“私有方法”没有可观察到的外部结果,您确定要对此进行测试吗?也许不应该。
如果无论是否调用私有方法,最终结果都相同,并且您仍想观察其调用,则可以将该方法设为公共并将其移至其自己的类,然后模拟该类。然后你可以验证(使用 Mockito 或类似的框架)你的方法是否被调用。
代码覆盖工具通过在测试实际运行之前重写字节码来做这种事情。所以,它必须是可能的,但它不是微不足道的。
更新:编写一个要求调用“正确”私有方法的单元测试会使重构工作变得非常痛苦,因为那时您必须重新编写所有测试。这违背了测试的目的。
作为解决方案之一,可以使用内部类的代理。您需要在每个必须测试的类中添加内部类。但对于大型产品项目来说,这不是很好的解决方案。它需要创建添加脚本以从您的发布文件(jar/war)中删除生成的类。
但更简单的方法将使用 PowerMock,如下面的评论(或上层:)) - http://code.google.com/p/powermock/wiki/MockPrivate
您可以检查 java 仪器以执行此操作
是否有可能为所讨论的类提供另一个对象,将私有方法移至该对象并使其公开?在这种情况下,很容易为该接口创建一个测试假人。