我正在使用Mockito为现有课程编写一些Java单元测试。但是,我无法提取这个类的对象作为嵌套调用的一部分调用方法的参数。
示例:
public class SomeClass {
public SomeClass() {
//...
}
public someMethod(Foo foo) {
// Bar bar = ...
someOtherMethod(bar);
}
private someOtherMethod(Bar bar) {
//...
}
}
我想捕获someOtherMethod()
的参数并验证bar
是否应该是什么。我可以使用ArgumentCaptor
或Mockito中的其他功能吗?
答案 0 :(得分:2)
模拟someOtherMethod
不太可能为您提供有用的结果。 someMethod
是您公开API的一部分,但someOtherMethod
不是;一般来说,测试合同很重要(someMethod的返回值和副作用),但它是一个反模式来测试实现(someMethod调用的私有方法)。
someMethod
的结果和副作用,并将其实现视为黑盒子。你可能甚至不需要使用Mockito。这是测试驱动开发的最纯粹形式:它可以让您重构someMethod
,可能完全省略对someOtherMethod
的调用或缓存结果(等)而无需编辑测试。someOtherMethod
调用外部服务,请将其设置为SomeClass实例上的可访问或可设置字段,并改为模拟该服务。
与其他服务的互动可以合理地视为一般合同的一部分;这就是Mockito的设计理念。someOtherMethod
足够独立,您希望单独测试someMethod
,请考虑将其设为包私有或受保护。这样你可以在测试中使用虚拟实现覆盖它,也可能在代码中的其他位置覆盖它 - 毕竟,它现在已成为someMethod
合同的一部分,对吧?如果它是大的或不透明的,你也可以考虑将它作为一个单独的可模拟类。另请参阅Programmers.SE中的"How do I unit test private methods?"或StackOverflow上的"How to use Mockito when we cannot pass a mock object to an instance of a class"。
答案 1 :(得分:0)
一个选项是使用存储这些参数的类重写SomeClass,并使它们可供您进行验证。优雅的选项是custom argument matchers。
答案 2 :(得分:0)
是
@Spy
private SomeClass someClassSpy;
@Captor
private ArgumentCaptor<Bar> barCaptor;
...
verify(someClassSpy).someOtherMethod(barCaptor.capture());
Bar bar = barCaptor.getValue();
assertThat(bar, is(...));