Протестируйте RabbitTemplate # convertAndSend как лямбду с помощью Mockito & JUnit - PullRequest
0 голосов
/ 05 сентября 2018

Я пытаюсь проверить метод RabbitTemplate # convertAndSend , который записан как лямбда, например:

// other stuff omitted for brevity

        rabbitTemplate.convertAndSend(myQueue, jsonString, message -> {
        message.getMessageProperties().setPriority(priority);
        return message;
        });

// other stuff omitted for brevity

Тестовый пример, который я пытаюсь сделать, это тот, где ArgumentCaptor используется для проверки того, что метод вызывается с правильными параметрами.

@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...
));

}

На шаге проверки проверка не пройдена, так как аргументы разные.

Wanted:
<Capturing argument>,
<Capturing argument>,
interface org.springframework.amqp.core.MessagePostProcessor

Actual invocation:
"myQueue",
"myJson",
com.example.notification.service.NotificationService$$Lambda$5/73698537@5bda80bf

Я пробовал несколько других Matchers от mockito и hamcrest, но безрезультатно.

Итак, мои вопросы:

  1. Как можно проверить подобные вещи?

  2. Это даже хорошая практика или есть другие / лучшие способы проверить отправку шаблонов кролика?

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Вы почти все поняли, за исключением последнего совпадения ArgumentMatchers.eq(MessagePostProcessor.class).

Вы фактически запрашиваете Mockito для совпадения Equatility с классом параметра. Вы должны скорее соответствовать против:

  • тип параметра с использованием ArgumentMatchers.any(MessagePostProcessor.class)
  • или фактическое значение ArgumentMatchers.eq(expectedMessageProcessor), если оно у вас есть
  • или аргумент-захватчик, если вам нужно проверить значение параметра

В этом конкретном случае, однако, если вы используете первую опцию, вы можете столкнуться с проблемой компилятора, так как класс RabbitTemplate имеет два похожих метода:

  • convertAndSend (String, String, Object)
  • convertAndSend (String, Object, MessagePostProcessor)

Чтобы решить эту проблему, вы можете принудительно настроить тип второго параметра на объект:

Mockito.verify(rabbitTemplate).convertAndSend(captor.capture(), (Object) captor.capture(),
            Mockito.any(MessagePostProcessor.class));

Или, лучше, иметь два разных ArgumentCaptor s для двух разных параметров:

ArgumentCaptor<String> routingKeyCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<Object> messageCaptor = ArgumentCaptor.forClass(Object.class);

...

verify(rabbitTemplate).convertAndSend(routingKeyCaptor.capture(), messageCaptor.capture(), any(MessagePostProcessor.class));

Надеюсь, это поможет!

0 голосов
/ 06 сентября 2018

Я думаю, все зависит от того, что вы действительно пытаетесь проверить и какую ценность для бизнеса это добавляет.

  1. Вы хотите протестировать сам RabbitTemplate? В репозитории Spring есть тесты для этого, но ИМХО вам не нужно этого делать.
  2. Вы тестируете Spring Service и должны убедиться, что сообщение отправлено?
  3. Хотите, чтобы сообщение достигло пункта назначения?

Для (1) есть несколько примеров именно того типа тестов, которые вы пишете в Spring Framework здесь, в своих модульных тестах для RabbitTemplate.

Например, проверка того, что базовый ConnectionFactory на самом деле создал канал :

    txTemplate.execute(status -> {
        template.convertAndSend("foo", "bar");
        return null;
    });
    txTemplate.execute(status -> {
        template.convertAndSend("baz", "qux");
        return null;
    });
    verify(mockConnectionFactory, Mockito.times(1)).newConnection(any(ExecutorService.class), anyString());
    // ensure we used the same channel
    verify(mockConnection, times(1)).createChannel();

Для (2), описанного выше, вам не нужно использовать захват аргументов и т. Д. Вы можете добавить макет RabbitTemplate в сервис, и мне лично нравится либо проверять аргумент, с которым я вызвал метод, либо использовать Mockito#any и т. Д.

К вашему сведению, с точки зрения утверждений, я бы также взглянул на AssertJ , у него хороший штамп одобрения от Spring, и свободный API для него (особенно с intellisense) делает это очень прост в использовании.

Для (3) я настоятельно рекомендую https://www.testcontainers.org/ (если вы используете docker), и я не проверил его, но может быть JUnit @Rule для создания брокера RabbitMQ (Я должен проверить это). Я сделал что-то подобное для ActiveMQ Artemis, который очень быстро запускает брокера для вас, и вы можете использовать сообщения, поставленные в очередь на него.

...