I am trying to test the RabbitTemplate#convertAndSend method that is written as a lambda, like so:
// other stuff omitted for brevity
rabbitTemplate.convertAndSend(myQueue, jsonString, message -> {
message.getMessageProperties().setPriority(priority);
return message;
});
// other stuff omitted for brevity
The test case I am trying to do is one where an ArgumentCaptor
is being used in order to verify that the method is called with correct parameters.
@Test
public void givenMyNotification_whenElementIsSent_thenSetPriorityAndSendValidParameters() {
final ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
final int expectedPriority = 5;
final Notification expected = TestUtils.getNotification();
testClass.handleNotification(expected);
verify(rabbitTemplate).convertAndSend(captor.capture(), captor.capture(),
ArgumentMatchers.eq(MessagePostProcessor.class));
// assertThat...
));
}
The test fails at the verify step because the arguments are different.
Wanted:
<Capturing argument>,
<Capturing argument>,
interface org.springframework.amqp.core.MessagePostProcessor
Actual invocation:
"myQueue",
"myJson",
com.example.notification.service.NotificationService$$Lambda$5/73698537@5bda80bf
I have tried several other Matchers from mockito and hamcrest but to no avail.
So, my questions are:
How does one test this kind of a thing?
Is this even a good practice or are there other/better ways to test rabbit template sending?
You almost get it all right, except for the last matcher ArgumentMatchers.eq(MessagePostProcessor.class)
.
You actually ask Mockito to match for equatility to the class of the parameter. You should rather match against:
ArgumentMatchers.any(MessagePostProcessor.class)
ArgumentMatchers.eq(expectedMessageProcessor)
if you happen to have itIn this particular case however, if you use the first option, you may run into a compiler issue, as RabbitTemplate
class has two similar methods:
To solve this you can force the type of the second parameter to object like this :
Mockito.verify(rabbitTemplate).convertAndSend(captor.capture(), (Object) captor.capture(),
Mockito.any(MessagePostProcessor.class));
Or better, have two different ArgumentCaptor
s for two different parameters:
ArgumentCaptor<String> routingKeyCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<Object> messageCaptor = ArgumentCaptor.forClass(Object.class);
...
verify(rabbitTemplate).convertAndSend(routingKeyCaptor.capture(), messageCaptor.capture(), any(MessagePostProcessor.class));
Hope this helps !