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

问题描述 投票:0回答:1

当多次在mock上调用相同的方法时,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???

    }

}

在上面的示例中,尽管

verifyNoMoreInteractions(myInterfaceMock)
尚未得到验证,但
verify(myInterfaceMock).doSomething(3)
通过了。这意味着仍然与模拟进行交互(即调用
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>  
java unit-testing mockito
1个回答
2
投票

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

@ExtendWith(MockitoExtension.class)
)。

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

STRICT_STUBS

@孵化公共静态最终严格性STRICT_STUBS

确保干净的测试,减少测试代码重复,改进 可调试性。提供灵活性和性能的最佳组合 生产率。强烈推荐。计划作为 Mockito v3 的默认设置。

如果您使用 Mockito.verifyNoMoreInteractions(Object...) 您不再需要 显式验证存根调用。它们会自动验证 为你。

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

这是什么意思?如果我们举个例子,给出的问题中,编写测试完全省略对

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 怎么知道叫什么?因为它分析存根。 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)
是多余的。

如果需要,可以通过将

verify()
更改为
Strictness
来启用对
WARN
的各个调用的自动验证,这可以通过
@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 肯定会减少编写的测试代码量

© www.soinside.com 2019 - 2024. All rights reserved.