- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
当多次在模拟上调用相同的方法时,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/
当多次在模拟上调用相同的方法时,Mockito 似乎错误地解释了 verifyNoMoreInteractions()。在下面的示例中,someInterface.doSomething(param)
我有这段代码要进行单元测试: public void method(Set fooList){ for (Foo f : fooList) { EnumClass i = f.g
我想确保每个测试都验证与其模拟的所有交互,所以我只是添加了一个用 @After 注释的方法,带有 verifyNoMoreInteractions,所有模拟作为参数。 @After public vo
当我排除 verifyNoMoreInteractions(daoInteractor) 行时,我的测试将通过。我认为像我所做的那样在测试结束时放置 verifyNoMoreInteractions(
Mockito 中的 verifyNoMoreInteractions 和 verifyZeroInteractions 有什么区别?两者是同一种方法吗? 最佳答案 显然,verifyZeroInte
我是一名优秀的程序员,十分优秀!