更新:这个答案发生了很大变化,因为 Mockito 2 中提供了严格的模拟,而 Mockito 3 中默认提供了对严格存根的强制执行。使用 strict 和 lenient 模式配置这些模拟和存根并查看 mockito issue 769 以获取文档和进度。
在 Mockito 2 之前,这不是 Mockito 可以轻松做到的。 EasyMock 的默认严格模拟确保 (1) 意外交互立即失败和 (2) 所有预期交互发生;除了verifyNoMoreInteractions(它不会立即失败,而是在测试结束时)之外,Mockito 没有任何设置。这是philosophical design decision on Mockito's part,请参阅this thread,Mockito 的发起者会进一步讨论它。
事实上,Mockito 的when 语法取决于它允许意外交互,因为意外交互告诉 Mockito 调用了哪个方法:
when(mockFoo.someMethod()).thenReturn(someValue);
// ^^^^^^^^^^^^^^^^^^^^ Java calls this first to get an argument for when,
// which is how Mockito knows which method to stub:
// it's always the last one called.
能够容忍意外调用的 EasyMock 模拟被命名为“nice mocks”; Mockito 的一大卖点是默认情况下模拟很好,因此它们通常可以容忍与被测试行为无关的调用。这确实使调试更加困难,因为 Mockito 不会像 EasyMock 那样在意外交互时立即失败,但它也使测试不那么脆弱——更可能安全的更改仍然会破坏测试,因为 EasyMock 模拟接到一个意想不到的电话。 在继续进行之前,请与您的团队确认他们是否会对您的选择感到满意:严格的模拟语义对于 Mockito 来说相对较新,并且可能存在很大的错误假设作为框架变化的交易。 (到那时,在看到替代方案之后,他们可能会让你使用 EasyMock!)
要在 Mockito 2+ 中使用严格的模拟,请参阅syntax and libraries in Mockito issue 769。这可能是从 Mockito 1.x 升级的好理由。
要在 Mockito 1.x 中模拟严格的模拟,您需要设置一个未通过测试的默认答案,并仅使用 doVerb 方法(doAnswer 、doReturn、doThrow 等)。此语法向 Mockito 发出警告,它需要停用您的存根行为。要创建默认答案,您可以为单个方法(首选)或单个模拟上的所有方法设置行为。
public class ThrowingAnswer extends Answer<Object> {
@Override public Object answer(InvocationOnMock invocation) {
throw new AssertionError("Unexpected invocation: " + invocation);
}
}
// apply to the entire object:
YourObject yourObject = Mockito.mock(YourObject.class, new ThrowingAnswer());
// or per-method:
YourObject yourObject = Mockito.mock(YourObject.class);
doAnswer(new ThrowingAnswer()).when(yourObject).scaryMethod(any());
Mockito 将始终返回最后定义的匹配链上的行为,并且仅在没有匹配的链时使用默认答案,因此您应该能够使用 doVerb 方法定义任意数量的链来覆盖该行为。