Предыдущий интеграционный тест использует текущее сообщение очереди теста - PullRequest
0 голосов
/ 11 января 2020

Поэтому я пытаюсь использовать некоторые очереди в моем проекте (rabbitmq). Я решил создать простые интеграционные тесты издателя / получателя.

Итак, я сделал простой отправитель

@Component
public class QueueSender {
    ...
    public void sendMessage(@RequestParam String message) {
        rabbitTemplate.convertAndSend(queue, message);
    }
}

и соответствующий тест

@SpringBootTest(classes = QueueSender.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@Import(RabbitAutoConfiguration.class)
class QueueSenderTest {
    ... --docker rabbitmq instance is one for all tests.
    @Test
    void shouldSendMessageToQueue() {
        String message = "hello world";

        queueSender.sendMessage(message);

        Object response = rabbitTemplate.receiveAndConvert(queue, MAX_TIMEOUT_MILLIS);
        assertEquals(message, response);
    }
}

и простой получатель

@Component
public class QueueListener {

    @RabbitListener(queuesToDeclare = @Queue("${queues.listener}"))
    public void listener(Message object) {
        System.out.println("received " + object);
    }

}

и соответствующий тест

@SpringBootTest(classes = QueueListener.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@Import(RabbitAutoConfiguration.class)
class QueueListenerTest {
    ... --docker rabbitmq instance is one for all tests.
    @Test
    void shouldFireListenerOnNewMessageOnQueue() {
        String message = "hello world";
        ArgumentCaptor<Message> argument = ArgumentCaptor.forClass(Message.class);

        rabbitTemplate.convertAndSend(queue, message);

        verify(queueListener, timeout(MAX_TIMEOUT_MILLIS)).listener(argument.capture());
        assertEquals(message, new String(argument.getValue().getBody()));
    }
}

Конфигурация очередей помещена в application.properties

queues:
    listener: "listen-queue-name"
    sender: "sender-queue-name"

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

queues:
    listener: "listen-queue-name"
    sender: "listen-queue-name"

В этом случае всегда происходит сбой SenderTest.

Так что, когда я отлаживаю SenderTest, кажется, что пружинный контекст предыдущего теста потребляет сообщение, поскольку отладчик останавливается в QueueListener, который должен даже не в контексте теста QueueSender -.-

Забавный факт, что перемещение одного из этих классов теста в другой пакет решает проблему, поэтому пробный SenderTest запускается так быстро, что RabbitListener из предыдущего теста все еще регистрируется.

DirtiesContext также работает, но я не хочу его использовать. Есть идеи?

Ответы [ 2 ]

0 голосов
/ 11 января 2020

Не совсем ответ на вашу проблему, но скорее предложение. Вы можете попробовать использовать тестовые контейнеры для RabbitMQ. По сути, ваш тестовый пример будет

1 - запустить тестовый контейнер RabbitMq, который создаст очередь.

2 - выполнить ваши тесты

3 - уничтожить тестовый контейнер.

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

Тестовый контейнер: https://www.testcontainers.org/modules/rabbitmq/

0 голосов
/ 11 января 2020

из пружины документация

Среда тестирования Spring кэширует контексты приложения между тестами. Поэтому, если ваши тесты используют одну и ту же конфигурацию (независимо от того, как она обнаружена), потенциально длительный процесс загрузки контекста происходит только один раз.

Так что это ваша проблема.

...