Mockito убедитесь, что определенная лямбда была передана в качестве аргумента в методе mock
Я хочу проверить следующий метод:
public void dispatchMessage(MessageHandler handler, String argument1, String argument2, Long argument3) {
handler.registerMessage(() -> {
dispatcher.dispatch(argument1,
argument2,
argument3);
});
}
здесь MessageHandler
- вспомогательный класс, который примет функциональную реализацию интерфейса в виде лямбды и сохранит ее для последующего выполнения.
есть ли способ проверить с mockito, что dispatchMessage
метод глумились 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/379645464@48f278eb
фактический вызов имеет разные аргументы:
..........Lambda/482052083@2f217633
что имеет смысл, так как mockito пытается сравнить две разные реализации функционального интерфейса, которые имеют другой хэш-код.
Итак, есть какой-то другой способ проверить, что метод dispatchMessage()
был вызван с лямбдой, которая возвращает void и имеет метод тела
dispatcher.dispatch("activityId", "ctxId", 1l,);
?
1 ответов
Да, вы можете. Фокус здесь в том, что вы должны добраться до экземпляра лямбды, который передается в registerMessage
а затем выполните это выражение, а затем вы можете проверить результат.
С целью значимого примера я создал это 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
}
}
}
вы должны помнить, что лямбда-выражение-это просто короткая форма руки для передачи функции методу. В этом примере функция run
метод a 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);
}
}
есть ArgumentCaptor
для лямбда-выражения, которое мы используем при первой проверке registerMessage
. После этой проверки мы можем получить лямбда-выражение от похитителя. Тип лямбда-выражение-это Runnable
, как определено в . Следовательно, мы можем назвать run
метод на нем, а затем убедитесь, что dispatch
метод Dispatcher
был вызван со всеми соответствующими аргументами.