我想测试以下方法:
public void dispatchMessage(MessageHandler handler, String argument1, String argument2, Long argument3) {
handler.registerMessage(() -> {
dispatcher.dispatch(argument1,
argument2,
argument3);
});
}
其中,MessageHandler
是一个助手类,它将接受lambda形式的函数接口实现,并将其存储以供以后执行。
有没有一种方法可以用mockito验证模拟MessageHandler
的dispatchMessage
方法已经用特定的lambda表达式调用:
意思是,我能写这样一个测试吗:
@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
实际调用有不同的参数:
..........Lambda$27/482052083@2f217633
这是有道理的,因为mockito试图比较函数接口的两种不同实现,它们具有不同的哈希代码。
那么,是否有其他方法可以验证方法dispatchMessage()
是否已被lambda调用,该lambda返回void并具有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表达式只是将函数传递给方法的一种简短形式。在本例中,函数是Runnable
的run
方法。因此,MessageHandler
的接口的方法registerMessage
采用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
,我们在registerMessage
的第一次验证中使用它。验证之后,我们可以从捕获器中检索lambda表达式。lambda表达式的类型是Runnable
,如MessageHandler
接口中所定义的。因此,我们可以在其上调用run
方法,然后验证是否使用所有适当的参数调用了Dispatcher
上的dispatch
方法。
您想要评估lambdaargThat(a -> a.get()
,然后比较它的值:
when(dogObject.barkAt(argThat(a -> a.get().equals(PEOPLE_TO_BARK_AT)))).thenReturn(OUTCOME);
在特定lambda之外,您可以验证您的方法是否是用调用的。任何lambda表达式都是这样调用的:
verify(handler).registerMessage(any())
private fun <T> any(): T {
Mockito.any<T>()
return null as T
}