繁体   English   中英

Mockito 验证特定的 lambda 已作为 mock 方法中的参数传递

[英]Mockito verify that a specific lambda has been passed as an argument in mock's method

我想测试以下方法:

    public void dispatchMessage(MessageHandler handler, String argument1, String argument2, Long argument3) {

    handler.registerMessage(() -> {
        dispatcher.dispatch(argument1,
                argument2,
                argument3);
    });

}

其中MessageHandler是一个助手 class,它将接受 lambda 形式的功能接口实现,并将其存储以供以后执行。

有没有办法用 mockito 验证模拟的MessageHandlerdispatchMessage方法已经用特定的 lambda 表达式调用:

意思是,我可以写这样的测试吗:

        @Test
public void testDispatchMessage_Success() throws Exception {

    myMessageDispatcher.dispatchMessage(handler, "activityId", "ctxId", 1l, );

    verify(handler, times(1)).dispatchMessage(() -> {
        dispatcher
            .dispatch("activityId", "ctxId", 1l,);
    });

}

}

此测试将导致断言错误:Argument(s) are different: Wanted:

......Tests$$Lambda$28/379645464@48f278eb

实际调用有不同的 arguments:

..........Lambda$27/482052083@2f217633

这是有道理的,因为 mockito 试图比较功能接口的两个不同实现,它们具有不同的 hash 代码。

那么有没有其他方法可以验证方法dispatchMessage()是否已使用返回 void 的 lambda 调用并具有dispatcher.dispatch("activityId", "ctxId", 1l,);

是的你可以。 这里的技巧是你必须到达传递给registerMessage的lambda实例,然后执行该表达式,然后你可以验证结果。

为了一个有意义的例子,我创建了这个Handler类,它包含你要测试的dispatchMessage

public class Handler {

    private Dispatcher dispatcher = new Dispatcher();

    public void dispatchMessage(MessageHandler handler, String argument1, String argument2, Long argument3) {

        handler.registerMessage(() -> {
            dispatcher.dispatch(argument1,
                    argument2,
                    argument3);
        });

    }

    interface MessageHandler {
        void registerMessage(Runnable run);
    }

    static class Dispatcher {
        void dispatch(String a, String b, long c){
            // Do dispatch
        }
    }
}

你必须要记住的是,lambda表达式只是将函数传递给方法的简单形式。 在此示例中,该函数是Runnablerun方法。 因此, MessageHandler接口的方法registerMessageRunnable作为其参数。 我还包括Dispatcher一个实现,它从registerMessage调用。 对此的测试如下所示:

@RunWith(MockitoJUnitRunner.class)
public class HandlerTest {
    @Mock
    private Dispatcher dispatcher;
    @InjectMocks
    private Handler classUnderTest;
    @Captor
    private ArgumentCaptor<Runnable> registerMessageLambdaCaptor;

    @Test
    public void shouldCallDispatchMethod() {
        final String a = "foo";
        final String b = "bar";
        final long c = 42L;

        MessageHandler handler = mock(MessageHandler.class);

        classUnderTest.dispatchMessage(handler, a, b, c);

        verify(handler).registerMessage(registerMessageLambdaCaptor.capture());

        Runnable lambda = registerMessageLambdaCaptor.getValue();

        lambda.run();

        verify(dispatcher).dispatch(a, b, c);
    }
}

我们在registerMessage的第一次验证中使用了lambda表达式的ArgumentCaptor 在验证之后,我们可以从捕获者中检索lambda表达式。 lambda表达式的类型是Runnable ,如MessageHandler接口中所定义。 因此,我们可以在其上调用run方法,然后验证Dispatcher上的dispatch方法是否使用所有适当的参数进行调用。

在特定的lambda之外,您可以验证是否使用任何 lambda表达式调用了您的方法,如下所示:

    verify(handler).registerMessage(any())

    private fun <T> any(): T {
        Mockito.any<T>()
        return null as T
    }

你想评估 lambda argThat(a -> a.get()然后比较它的值:

when(dogObject.barkAt(argThat(a -> a.get().equals(PEOPLE_TO_BARK_AT)))).thenReturn(OUTCOME);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM