验证方法并行执行

Validate methods execute in parallel

我正在创建一个单元测试来显示两个方法并行执行。为此,我模拟了这两种方法,并让它们都有 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!! 的代码中,应该调用实际并行调用两个模拟方法的真实方法。或者,Answer 的两个实例应该被实现为并行执行,但是只有模拟的测试是没有用的。 鉴于此,按照我在示例中所做的那样配置的 inOrder 验证第二次调用发生在第一次调用结束之前(查看我添加的注释)。

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