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

时间:2017-01-04 11:38:49

标签: java lambda mockito

我想测试以下方法:

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

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

}

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

有没有办法验证mockito是否使用特定的lambda表达式调用了模拟dispatchMessage的{​​{1}}方法:

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

MessageHandler

此测试将导致断言错误: 争论是不同的!通缉:

        @Test
public void testDispatchMessage_Success() throws Exception {

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

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

}

}

实际调用有不同的参数:

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

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

还有其他方法来验证方法..........Lambda$27/482052083@2f217633 是否已使用返回void的lambda调用,并且具有body方法 dispatchMessage()

2 个答案:

答案 0 :(得分:17)

是的,你可以。这里的诀窍是你必须到达传递给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表达式只是将函数传递给方法的简单形式。在此示例中,函数是run的{​​{1}}方法。因此,Runnable接口的方法registerMessage会将MessageHandler作为其参数。 我还包含Runnable的实现,该实现从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); } } 的第一次验证中使用lambda表达式ArgumentCaptor。在验证之后,我们可以从捕获者中检索lambda表达式。 lambda表达式的类型为registerMessage,如Runnable接口中所定义。因此,我们可以在其上调用MessageHandler方法,然后验证run上的dispatch方法是否已使用所有适当的参数进行调用。

答案 1 :(得分:0)

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

    verify(handler).registerMessage(any())

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