为什么 mockito 会触发验证两次?
Why mockito will trigger the verify twice?
我在以下测试中注意到这个问题:
verify(mockedObject).functionCall(argThat(inputStream -> {
final String content = ... // read the inputStream
assertEquals(expectedContent, content);
return true;
}));
尽管 assertEquals
断言为真,但它实际上会失败。我调试测试,发现两次到达lambda函数,第二次,流的游标在流的末尾。这就是它失败的原因。
所以我必须先重置流:
verify(mockedObject).functionCall(argThat(inputStream -> {
inputStream.reset();
final String content = ... // read the inputStream
assertEquals(expectedContent, content);
return true;
}));
问题来了,为什么lambda会被触发两次?这是设计使然吗?有文档吗?
Mockito 版本:2.22
Junit 版本:5.6.0
Java版本:1.8
更新
该方法只被调用一次,并且两次 lambda 调用的输入是完全相同的输入。实际上,它们是同一个对象。我唯一需要做的就是重置流,因为它已被第一个 lambda 调用耗尽。
我不会说这是“设计使然”,而是说这是当前实现所做的。执行断言的 Mockito Times
class 具有以下方法(我使用的是最新版本,所以 YMMV):
public void verify(VerificationData data) {
List<Invocation> invocations = data.getAllInvocations();
MatchableInvocation wanted = data.getTarget();
if (wantedCount > 0) {
checkMissingInvocation(data.getAllInvocations(), data.getTarget());
}
checkNumberOfInvocations(invocations, wanted, wantedCount);
}
checkMissingInvocation
和 checkNumberOfInvocations
都对所有调用列表执行独立过滤以保留相关的调用,因此您声明的任何匹配器最终都会为每次调用执行两次。这实际上是完全相同的调用:
List<Invocation> actualInvocations = findInvocations(invocations, wanted);
也许可以缓存过滤后的列表,但要点是,除非文档中另有说明,否则您不能假设您提供的函数只会执行一次。此外,谓词函数通常应该没有副作用。
我在以下测试中注意到这个问题:
verify(mockedObject).functionCall(argThat(inputStream -> {
final String content = ... // read the inputStream
assertEquals(expectedContent, content);
return true;
}));
尽管 assertEquals
断言为真,但它实际上会失败。我调试测试,发现两次到达lambda函数,第二次,流的游标在流的末尾。这就是它失败的原因。
所以我必须先重置流:
verify(mockedObject).functionCall(argThat(inputStream -> {
inputStream.reset();
final String content = ... // read the inputStream
assertEquals(expectedContent, content);
return true;
}));
问题来了,为什么lambda会被触发两次?这是设计使然吗?有文档吗?
Mockito 版本:2.22
Junit 版本:5.6.0
Java版本:1.8
更新
该方法只被调用一次,并且两次 lambda 调用的输入是完全相同的输入。实际上,它们是同一个对象。我唯一需要做的就是重置流,因为它已被第一个 lambda 调用耗尽。
我不会说这是“设计使然”,而是说这是当前实现所做的。执行断言的 Mockito Times
class 具有以下方法(我使用的是最新版本,所以 YMMV):
public void verify(VerificationData data) {
List<Invocation> invocations = data.getAllInvocations();
MatchableInvocation wanted = data.getTarget();
if (wantedCount > 0) {
checkMissingInvocation(data.getAllInvocations(), data.getTarget());
}
checkNumberOfInvocations(invocations, wanted, wantedCount);
}
checkMissingInvocation
和 checkNumberOfInvocations
都对所有调用列表执行独立过滤以保留相关的调用,因此您声明的任何匹配器最终都会为每次调用执行两次。这实际上是完全相同的调用:
List<Invocation> actualInvocations = findInvocations(invocations, wanted);
也许可以缓存过滤后的列表,但要点是,除非文档中另有说明,否则您不能假设您提供的函数只会执行一次。此外,谓词函数通常应该没有副作用。