为什么mockito会触发verify两次?

stszievb  于 2021-06-26  发布在  Java
关注(0)|答案(1)|浏览(449)

我在下面的测试中注意到这个问题:

verify(mockedObject).functionCall(argThat(inputStream -> {
    final String content = ... // read the inputStream
    assertEquals(expectedContent, content);
    return true;
}));

它实际上会失败,尽管 assertEquals Assert是正确的。我调试了这个测试,发现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调用耗尽了。

pwuypxnk

pwuypxnk1#

我不会说它是“设计的”,而是说它是当前实现所做的。Mockito Times 执行Assert的类具有以下方法(我使用的是一个非常新的版本,所以是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);

也许可以缓存过滤后的列表,但关键是,除非文档中另有规定,否则不能假设您提供的函数只执行一次。此外, predicate 函数通常被期望没有副作用。

相关问题