使用 Mockito 从链式方法中捕获参数
Capture Arguments from Chained Methods Using Mockito
我正在使用 Mockito 为现有 class 编写一些 Java 单元测试。但是,我无法提取此 class 的对象作为嵌套调用的一部分调用方法的参数。
示例:
public class SomeClass {
public SomeClass() {
//...
}
public someMethod(Foo foo) {
// Bar bar = ...
someOtherMethod(bar);
}
private someOtherMethod(Bar bar) {
//...
}
}
我想捕获 someOtherMethod()
的参数并验证 bar
是否正确。我可以使用 ArgumentCaptor
或 Mockito 中的其他功能来做到这一点吗?
一个选项是用 class 覆盖 SomeClass 来存储这些参数并使它们可供您进行验证。一个优雅的选项是 custom argument matchers.
模拟 someOtherMethod
不太可能为您提供有用的结果。 someMethod
是您 public API 的一部分,但 someOtherMethod
不是;通常,测试契约(someMethod 的 return 价值和副作用)很重要,但测试实现(someMethod 调用的私有方法)是一种反模式。
- 理想情况下,只需测试
someMethod
的结果和副作用,并将其实现视为黑盒。您可能甚至不需要为此使用 Mockito。这是最纯粹的测试驱动开发形式:它使您可以自由地重构 someMethod
,也许完全省略对 someOtherMethod
的调用或缓存结果(等)而无需编辑您的测试。
- 如果
someOtherMethod
调用外部服务,请将其设置为您的 SomeClass 实例上的可访问或可设置字段,然后模拟该服务。
与其他服务的交互可以合理地视为一般合同的一部分;这确实是 Mockito 的设计目的。
- 如果
someOtherMethod
足够独立以至于您想单独测试 someMethod
,请考虑将其设为包私有或受保护。这样你就可以在你的测试中用一个虚拟的实现来覆盖它,也可能在你的代码的其他地方——毕竟,它现在是你的 someMethod
合同的一个测试部分,对吧?如果它太大或不透明,您还可以考虑将其设为单独的可模拟对象 class。
另请参阅 Whosebug 上的 "How do I unit test private methods?" in Programmers.SE, or "How to use Mockito when we cannot pass a mock object to an instance of a class"。
是的。
@Spy
private SomeClass someClassSpy;
@Captor
private ArgumentCaptor<Bar> barCaptor;
...
verify(someClassSpy).someOtherMethod(barCaptor.capture());
Bar bar = barCaptor.getValue();
assertThat(bar, is(...));
我正在使用 Mockito 为现有 class 编写一些 Java 单元测试。但是,我无法提取此 class 的对象作为嵌套调用的一部分调用方法的参数。
示例:
public class SomeClass {
public SomeClass() {
//...
}
public someMethod(Foo foo) {
// Bar bar = ...
someOtherMethod(bar);
}
private someOtherMethod(Bar bar) {
//...
}
}
我想捕获 someOtherMethod()
的参数并验证 bar
是否正确。我可以使用 ArgumentCaptor
或 Mockito 中的其他功能来做到这一点吗?
一个选项是用 class 覆盖 SomeClass 来存储这些参数并使它们可供您进行验证。一个优雅的选项是 custom argument matchers.
模拟 someOtherMethod
不太可能为您提供有用的结果。 someMethod
是您 public API 的一部分,但 someOtherMethod
不是;通常,测试契约(someMethod 的 return 价值和副作用)很重要,但测试实现(someMethod 调用的私有方法)是一种反模式。
- 理想情况下,只需测试
someMethod
的结果和副作用,并将其实现视为黑盒。您可能甚至不需要为此使用 Mockito。这是最纯粹的测试驱动开发形式:它使您可以自由地重构someMethod
,也许完全省略对someOtherMethod
的调用或缓存结果(等)而无需编辑您的测试。 - 如果
someOtherMethod
调用外部服务,请将其设置为您的 SomeClass 实例上的可访问或可设置字段,然后模拟该服务。 与其他服务的交互可以合理地视为一般合同的一部分;这确实是 Mockito 的设计目的。 - 如果
someOtherMethod
足够独立以至于您想单独测试someMethod
,请考虑将其设为包私有或受保护。这样你就可以在你的测试中用一个虚拟的实现来覆盖它,也可能在你的代码的其他地方——毕竟,它现在是你的someMethod
合同的一个测试部分,对吧?如果它太大或不透明,您还可以考虑将其设为单独的可模拟对象 class。
另请参阅 Whosebug 上的 "How do I unit test private methods?" in Programmers.SE, or "How to use Mockito when we cannot pass a mock object to an instance of a class"。
是的。
@Spy
private SomeClass someClassSpy;
@Captor
private ArgumentCaptor<Bar> barCaptor;
...
verify(someClassSpy).someOtherMethod(barCaptor.capture());
Bar bar = barCaptor.getValue();
assertThat(bar, is(...));