验证方法并行执行



我正在创建一个单元测试来显示两个方法并行执行。为此,我模拟了这两种方法,并使它们都有 2 秒的延迟。然后,我验证单元测试花费的时间少于 4(因此我可以确定操作不是按顺序执行的,因为这样将需要超过 4 [2*2] 秒)。

有没有更好的方法?

我会使用Inorder功能。这是两个方法来自同一个模拟的情况的示例:

@Test
public void foo() {
    MyClass mock = Mockito.mock(MyClass.class);
    Mockito.when(mock.methodOne())thenAnswer(new Answer<ReturnType>()
    {
        @Override
        public ReturnType answer(InvocationOnMock invocation) throws Throwable
        {
            // Implement the delay or parallel execution
            . . . 
            mock.methodThree(); // This invocation is just a hook to intercept the end of this method execution
            return something;
        }
    });
    Mockito.when(mock.methodTwo())thenAnswer(new Answer<ReturnType>()
    {
        @Override
        public ReturnType answer(InvocationOnMock invocation) throws Throwable
        {
            // Implement the delay or the parallel execution
            . . .
            mock.methodThree(); // This invocation is just a hook to intercept the end of this method execution
            return something;
        }
    });

    // Here there should be the call to the real method that calls the two methods in parallel: 
    // !!HERE!!
    // mock1.methodOne();
    // mock2.methodTwo();
    InOrder inOrder = Mockito.inOrder(mock1, mock2);
    inOrder.verify(mock1).methodOne(); //asserts that methodOne should be invoked first
    inOrder.verify(mock2).methodTwo(); //asserts that methodTwo should be invoked after methodOne
    inOrder.verify(mock3, Mockito.calls(2)).methodThree(); //asserts that methodThree, that is invoked at the end of methodOne, is invoked after the methodTwo invocation.  These asserts together tell us that methodTwo was called during the execution of methodOne.
}

您还可以将 InOrder 与多个模拟一起使用:

@Test
public void foo() {
    MyClass mock1 = Mockito.mock(MyClass.class);
    MyClass mock2 = Mockito.mock(MyClass.class);
    OtherClass mock3 = Mockito.mock(OtherClass.class);
    Mockito.when(mock1.methodOne())thenAnswer(new Answer<ReturnType>()
    {
        @Override
        public ReturnType answer(InvocationOnMock invocation) throws Throwable
        {
            // Implement the delay or the parallel execution
            . . .
            mock3.methodThree(); // This invocation is just a hook to intercept the end of this method execution
            return something;
        }
    });
    Mockito.when(mock2.methodTwo())thenAnswer(new Answer<ReturnType>()
    {
        @Override
        public ReturnType answer(InvocationOnMock invocation) throws Throwable
        {
            // Implement the delay or the parallel execution 
            . . .
            mock3.methodThree(); // This invocation is just a hook to intercept the end of this method execution
            return something;
        }
    });

    // Here there should be the call to the real method that calls the two methods in parallel: 
    // !!HERE!!
    // mock1.methodOne();
    // mock2.methodTwo();
    InOrder inOrder = Mockito.inOrder(mock1, mock2);
    inOrder.verify(mock1).methodOne(); //asserts that methodOne should be invoked first
    inOrder.verify(mock2).methodTwo(); //asserts that methodTwo should be invoked after methodOne
    inOrder.verify(mock3, Mockito.calls(2)).methodThree(); //asserts that methodThree, that is invoked at the end of methodOne, is invoked after the methodTwo invocation. These asserts together tell us that methodTwo was called during the execution of methodOne.
}

在这个例子中,mock3 只是一个实例,它的唯一目的是钩住两个方法的执行结束,所以应该用 doNothing 来模拟它。也许在您的场景中,这可以以不同的方式实现。

编辑:我现在将更好地解释我的答案:在我分享的示例中,只有模拟,因此测试毫无用处。在我添加!!HERE!!的代码中,应该调用实际并行调用两个模拟方法的 real 方法。或者,应该实现两个Answer实例以并行执行,但只有模拟的测试是没有用的。鉴于此,按照我在示例中配置的 inOrder 验证第二次调用是否发生在第一次调用结束之前(查看我添加的注释)。

有关 InOrder 接口的更多信息:http://site.mockito.org/mockito/docs/current/org/mockito/InOrder.htmlhttp://www.tutorialspoint.com/mockito/mockito_ordered_verification.htm

最新更新