Mockito verify that a specific lambda has been passed as an argument in mock's method
Yes, you can. The trick here is that you have to get to the instance of the lambda that is passed to the registerMessage
and then execute that expression and then you can verify the result.
For the purpose of a meaningful example I created this Handler
class that contains the dispatchMessage
that you want to test:
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
}
}
}
What you have to remember is that a lambda expression is just a short hand form to pass a function to a method. In this example the function is the run
method of a Runnable
. Therefore the method registerMessage
of the interface for MessageHandler
takes a Runnable
as it's argument.
I also included an implementation for the Dispatcher
, which is called from within registerMessage
.
The test for this looks like this:
@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);
}
}
There is an ArgumentCaptor
for the lambda expression which we use in the first verification of the registerMessage
. After that verification we can retrieve the lambda expression from the captor. The type of the lambda expression is Runnable
, as defined in the MessageHandler
interface. Hence we can call the run
method on it and then verify that the dispatch
method on the Dispatcher
was called with all the appropriate arguments.