Home > Net >  Mocking MessegePostProcessor Interface in JmsTemplate
Mocking MessegePostProcessor Interface in JmsTemplate

Time:04-03

I'm new in Mockito and I'm facing an issue regarding a stubbing argument mismatch.

so far I thought this would works fine since in my implementation jmsTemplate is a depedency of jmsTemplateService and everything is injected via @Mock and @InjectMocks

and theoretically I'm mocking the execution of the invoked dependent method

convertAndSend(String destinationName, final Object message, final MessagePostProcessor postProcessor)

main part of test

Message message = Mockito.mock(Message.class);

MessagePostProcessor messagePostProcessor = (x) -> message;

doNothing()
           .when(jmsTemplate)
           .convertAndSend(queue, obj, messagePostProcessor);

jmsTemplateService.sendMessage(queue, obj);

but mockito throws a stubbing argument mismatch error which actually made me understand I'm not stubbing correctly.

- this invocation of 'convertAndSend' method:
    jmsTemplate.convertAndSend(
    "queueA",
     Obj(),
  com.example.JmsTemplateService$$Lambda$383/0x0000000800dd9440@5fb7183b
);
    -> at com.example.JmsTemplateService.sendMessage(JmsTemplateService.java:64)
 - has following stubbing(s) with different arguments:
    1. jmsTemplate.convertAndSend(
    "queueA",
   Obj(),
   com.example.JmsTemplateServiceTest$$Lambda$382/0x0000000800ddb360@74ad8d05
);

it seems the last parameter is the actual problem but I don't know how to capture it without mocking the jmsTemplate dependencies too.

this is the current implementation of the JmsTemplateService.sendMessage(String queue, Obj obj)

 public void sendMessage(String queue, Object obj) {
        
      try {
           jmsTemplate.convertAndSend(queue, obj, message -> {
           //do stuffs before sending the message
           });
      }catch (Exception e) {
       //handle exception
    }

any hint of what could be wrong in mocking the convertAndSend method?

Thank you very much for the help!

CodePudding user response:

It is because the MessagePostProcessor you use to stub the JmsTemplate is different from the actual instance that is passed to the JmsTemplate when the test method is executed.

The MessagePostProcessor passed to the mocked JmsTemplate is a new instance that is created internally inside the test method while the one you use for stubbing is created outside the test method. They are apparently two different instances.

Since convertAndSend() in JmsTemplate return void , there is nothing for you to stub. You can simply verify if it is executed correctly with the expected parameters after executing the test method. Something likes :

@ExtendWith(MockitoExtension.class)
public class JmsTemplateServiceTest {

    @Mock
    private JmsTemplate jmsTemplate;

    private JmsTemplateService jmsTemplateService;

    @BeforeEach
    public void init() {
        jmsTemplateService = new JmsTemplateService(jmsTemplate);
    }

    @Test
    public void convertAndSendTest() {
        Object someObject = ....;
        jmsTemplateService.sendMessage("queueA", someObject);
        verify(jmsTemplate).convertAndSend(eq("queueA"), eq(someObject), any());
    }

}

CodePudding user response:

it seems the last parameter is the actual problem but I don't know how to capture it without mocking the jmsTemplate dependencies too.

Actually, you are mocking jmsTemplate, otherwise it'd throw an exception because jmsTemplate variable is not a mock.

doNothing()
       .when(jmsTemplate) <- a mock is expected to be used here
       .convertAndSend(queue, obj, messagePostProcessor);

You're right that the last parameter is the actual problem since different instances are being used.

The first instance is defined by your lambda in the test:

MessagePostProcessor messagePostProcessor = (x) -> message;

And the second one is defined with the other lambda when you perform the call to jmsTemplate.convertAndSend(..., ..., message -> {...})

Posibly you're getting that error because you're verifying that the jmsTemplate.convertAndSend(...) was called with the params you defined in the tests. Something like:

verify(jmsTemplate).convertAndSend(queue, obj, messagePostProcessor);

What you can do is expect any() as a 3rd argument in that verify, and expect something like ArgumentsMatchers.eq(queue) and ArgumentsMatchers.eq(obj) as other arguments:

verify(jmsTemplate).convertAndSend(ArgumentsMatchers.eq(queue), ArgumentsMatchers.eq(obj), any());
  • Related