6

I am using SpringAMQP where I am testing producer method (basically AMQP template) which is like this.

public void send(Message message, Throwable error, String queue, String routingKey) {

    this.amqpTemplate.convertAndSend(
        RabbitConfiguration.ERROR_EXCHANGE,
        RabbitConfiguration.ERROR_ROUTING_KEY,
        message,
        messageMetaData -> {

            messageMetaData.getMessageProperties().getHeaders().put("x-death-reason", error.getMessage());

            return messageMetaData;
        }
    );
}

I am testing this code with following

import static org.hamcrest.Matchers.any;
....
@Test
public void will_create_error_message_if_incorrect_payload_is_given() {

    AmqpTemplate amqpTemplate = mock(AmqpTemplate.class);
    Throwable throwable = mock(Throwable.class);
    when(throwable.getMessage()).thenReturn("first");
    when(throwable.getStackTrace()).thenReturn(null);

    ErrorMessageProducer errorMessageProducer = new ErrorMessageProducer(amqpTemplate);

    Message message = MessageBuilder.withBody("test".getBytes()).build();

    verify(amqpTemplate).convertAndSend(
        eq(RabbitConfiguration.ERROR_EXCHANGE),
        eq(RabbitConfiguration.ERROR_ROUTING_KEY),
        any(Message.class),
        Mockito.any()
    );
}

But I am getting Invalid use of argument matchers! 4 matchers expected, 3 recorded. Is there any way I can test with Lambda or ignore Lambda altogether.

nicholasnet
  • 2,117
  • 2
  • 24
  • 46
  • 3
    Seems that the error is reported because of `any(Message.class)`, which, given the static import `import static org.hamcrest.Matchers.any` is not a Mockito matchers...
    Mockito also has a `any` matcher (with same API/syntax)
    – ernest_k May 01 '18 at 18:30
  • 1
    You were right :) Lack of sleep and coffee. Its working now. – nicholasnet May 01 '18 at 18:35

1 Answers1

5

The problem is because you are using wrong any().

verify(amqpTemplate).convertAndSend(
    eq(RabbitConfiguration.ERROR_EXCHANGE),
    eq(RabbitConfiguration.ERROR_ROUTING_KEY),
    any(Message.class),
    Mockito.any()
);

Here your 3rd argument using any from org.hamcrest.Matchers.any, however 4th argument uses right Mockito.any(). So 3rd argument isn't detected as a matcher, but is threated like a usual argument.

To check your lambda you should probably use ArgumentCaptor.

ArgumentCaptor<Runnable> argument = ArgumentCaptor.forClass(Runnable.class);
verify(mock).doSomething(any(), argument.capture());
argument.getValue().run();
...verify that lambda called your services...

You can change Runnable to any type of function your lambda actually represents: i.e. Function/Callable.

Ruslan Akhundov
  • 2,178
  • 4
  • 20
  • 38
  • You are right but is there anyway to test lambda content as well. – nicholasnet May 01 '18 at 18:42
  • @nicholasnet can you please clarify what do you mean by that? Anymatcher should work well. If you want check, if lambda passed in your method, contains proper calls to other services, you can capture lambda, call it, and check if your services were called properly. If thats not what you are asking about, please clarify – Ruslan Akhundov May 01 '18 at 18:50
  • You are right AnyMatcher is working that’s why I accepted the answer. I guess what I am looking now is how to capture Lambda and call it and check it later. – nicholasnet May 01 '18 at 18:59
  • Ok I will give that a try thank you very much for your help. – nicholasnet May 01 '18 at 19:18