I want to test the following method:
public void dispatchMessage(MessageHandler handler, String argument1, String argument2, Long argument3) {
handler.registerMessage(() -> {
dispatcher.dispatch(argument1,
argument2,
argument3);
});
}
Where MessageHandler
is a helper class which will accept a Functional Interface implementation in the form a lambda, and store it for later execution.
Is there a way to verify with mockito that the dispatchMessage
method of the mocked MessageHandler
has been called with the specific lambda expression:
Meaning, can I write such a test:
@Test
public void testDispatchMessage_Success() throws Exception {
myMessageDispatcher.dispatchMessage(handler, "activityId", "ctxId", 1l, );
verify(handler, times(1)).dispatchMessage(() -> {
dispatcher
.dispatch("activityId", "ctxId", 1l,);
});
}
}
This test will result in assertion error: Argument(s) are different! Wanted:
......Tests$$Lambda$28/379645464@48f278eb
Actual invocation has different arguments:
..........Lambda$27/482052083@2f217633
which makes sense since mockito tries to compare two different implementations of the functional interface, which have a different hash code.
So is there some other way to verify that the method dispatchMessage()
has been called with a lambda that returns void and has a body method of
dispatcher.dispatch("activityId", "ctxId", 1l,);
?
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 thedispatchMessage
that you want to test: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 aRunnable
. Therefore the methodregisterMessage
of the interface forMessageHandler
takes aRunnable
as it's argument. I also included an implementation for theDispatcher
, which is called from withinregisterMessage
. The test for this looks like this:There is an
ArgumentCaptor
for the lambda expression which we use in the first verification of theregisterMessage
. After that verification we can retrieve the lambda expression from the captor. The type of the lambda expression isRunnable
, as defined in theMessageHandler
interface. Hence we can call therun
method on it and then verify that thedispatch
method on theDispatcher
was called with all the appropriate arguments.