Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make JUnit take any Lambda expression

Tags:

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.

like image 823
nicholasnet Avatar asked May 01 '18 18:05

nicholasnet


1 Answers

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.

like image 85
Ruslan Akhundov Avatar answered Sep 28 '22 17:09

Ruslan Akhundov