我正在使用Mockito为现有类编写一些Java单元测试。但是,我在提取参数时遇到了问题,该类的对象使用这些参数作为嵌套调用的一部分来调用方法。
示例:
public class SomeClass {
public SomeClass() {
//...
}
public someMethod(Foo foo) {
// Bar bar = ...
someOtherMethod(bar);
}
private someOtherMethod(Bar bar) {
//...
}
}
我想捕获someOtherMethod()
的参数,并验证bar
是否应该是它。我可以使用ArgumentCaptor
或Mockito中的其他功能吗?
模拟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中的"当我们无法将mock对象传递给类的实例时,如何使用Mockito"。
一个选项是用一个类覆盖SomeClass,该类存储这些参数并使它们可供您验证。一个优雅的选择是自定义参数匹配器。
是。
@Spy
private SomeClass someClassSpy;
@Captor
private ArgumentCaptor<Bar> barCaptor;
...
verify(someClassSpy).someOtherMethod(barCaptor.capture());
Bar bar = barCaptor.getValue();
assertThat(bar, is(...));