gpt4 book ai didi

java - Mockito - verifyNoMoreInteractions - 使用不同参数的多次调用

转载 作者:太空宇宙 更新时间:2023-11-04 09:25:37 30 4
gpt4 key购买 nike

当多次在模拟上调用相同的方法时,Mockito 似乎错误地解释了 verifyNoMoreInteractions()。在下面的示例中,someInterface.doSomething(param) 被多次调用(对于传递的每个参数):

public interface SomeInterface {

int doSomething(int a);
}
public class SomeService {

private final SomeInterface someInterface;

public SomeService(SomeInterface someInterface) {
this.someInterface = someInterface;
}

public int callInterface(int... params) {
int sum = 0;
for (int param : params) {
sum += someInterface.doSomething(param); // call for each param
}
return sum;
}
}

测试:

@ExtendWith(MockitoExtension.class)
class SomeServiceTest {

@Test
public void myTest() {
SomeInterface myInterfaceMock = mock(SomeInterface.class);
SomeService myService = new SomeService(myInterfaceMock);

doReturn(1).when(myInterfaceMock).doSomething(1);
doReturn(2).when(myInterfaceMock).doSomething(2);
doReturn(3).when(myInterfaceMock).doSomething(3);

int sum = myService.callInterface(1, 2, 3);

assertEquals(1 + 2 + 3, sum);

verify(myInterfaceMock).doSomething(1);
verify(myInterfaceMock).doSomething(2);
verifyNoMoreInteractions(myInterfaceMock); // succeeds???

}

}

在上面的示例中,尽管 verify(myInterfaceMock).doSomething(3) 未经过验证,但 verifyNoMoreInteractions(myInterfaceMock) 通过了。这意味着仍然存在与模拟的交互(即调用myInterface.doSomething(3))。这是怎么回事?

注意:如果有另一个调用 SomeInterface.someOtherMethod 而不是 verifyNoMoreInteractions 会发出信号,但上面似乎没有检测到情况。

我的测试用例的依赖关系:

<dependencies>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>

最佳答案

分析文档并考虑来自 (@JBNizet) 的有用评论后,从 Mockito 版本 3.0 和 JUnit5 开始似乎是预期的行为(使用 Mockito 扩展 @ExtendWith(MockitoExtension.class))。

答案可以在Mockito Strictness API的javadoc中找到我们可以在哪里阅读:

STRICT_STUBS

@Incubating public static final Strictness STRICT_STUBS

Ensures clean tests, reduces test code duplication, improves debuggability. Offers best combination of flexibility and productivity. Highly recommended. Planned as default for Mockito v3.

If you use Mockito.verifyNoMoreInteractions(Object...) you no longer need to explicitly verify stubbed invocations. They are automatically verified for you.

因此 stub 方法调用会自动验证!

这是什么意思?如果我们举个例子,给出的问题中,编写测试完全省略对verify(myInterfaceMock).doSomething(x)的调用就足够了。只需将调用留给 verifyNoMoreInteractions(myInterfaceMock) 就足够了。因此这个测试也成功了:

@Test
public void myTest() {
SomeInterface myInterfaceMock = mock(SomeInterface.class);
SomeService myService = new SomeService(myInterfaceMock);

doReturn(1).when(myInterfaceMock).doSomething(1);
doReturn(2).when(myInterfaceMock).doSomething(2);
doReturn(3).when(myInterfaceMock).doSomething(3);

int sum = myService.callInterface(1, 2, 3);

assertEquals(1 + 2 + 3, sum);

verifyNoMoreInteractions(myInterfaceMock); // NOTE: no individual verify(myInterfaceMock) calls (!)

}

Mockito 怎么知道叫什么?因为它分析 stub 。 Mockito 根据这段代码找出应该验证哪些方法:

    doReturn(1).when(myInterfaceMock).doSomething(1);
doReturn(2).when(myInterfaceMock).doSomething(2);
doReturn(3).when(myInterfaceMock).doSomething(3);

Mockito,似乎在说“嘿伙计,你期待 myInterfaceMock 调用 doSomething(1),所以如果你调用 verifyNoMoreInteractions(),我将验证 doSomething(1) 是否真的被调用...所以个人期望 verify(myInterfaceMock).doSomething(1) 是多余的。

如果需要,可以通过将 Strictness 更改为 WARN 来启用对 verify() 的各个调用的自动验证,这可以通过 @MockitoSettings(strictness = Strictness.WARN)

来实现

以下版本的测试按最初预期失败:

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.WARN)
class SomeServiceTest {

@Test
public void myTest() {
SomeInterface myInterfaceMock = mock(SomeInterface.class);
SomeService myService = new SomeService(myInterfaceMock);

doReturn(1).when(myInterfaceMock).doSomething(1);
doReturn(2).when(myInterfaceMock).doSomething(2);
doReturn(3).when(myInterfaceMock).doSomething(3);

int sum = myService.callInterface(1, 2, 3);

assertEquals(1 + 2 + 3, sum);

verify(myInterfaceMock).doSomething(1);
verify(myInterfaceMock).doSomething(2);
verifyNoMoreInteractions(myInterfaceMock);

}

}

带有消息:

org.mockito.exceptions.verification.NoInteractionsWanted: 
No interactions wanted here:
-> at SomeServiceTest.myTest(SomeServiceTest.java:30)
But found this interaction on mock 'someInterface':
-> at SomeService.callInterface(SomeService.java:13)
***
For your reference, here is the list of all invocations ([?] - means unverified).
1. -> at SomeService.callInterface(SomeService.java:13)
2. -> at SomeService.callInterface(SomeService.java:13)
3. [?]-> at SomeService.callInterface(SomeService.java:13)

这似乎取决于测试的设计者他/她想要使用哪个 Strictess。新的默认严格性 - STRICT_STUBS 肯定会减少编写的测试代码量

关于java - Mockito - verifyNoMoreInteractions - 使用不同参数的多次调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57744435/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com