使用 TestContainer 运行集成测试时从数据库获取 null

问题描述 投票:0回答:1

我正在学习 Java、Spring,并且遇到了用于编写(单元/集成)测试的 TestContainers 库。我尝试编写一个示例应用程序,创建一个 RabbitMQ 生产者、消费者,然后为其编写一个测试用例,如下所示:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SampleITTest extends AbstractTestcontainers {
    @Autowired
    private WebTestClient webTestClient;

    private static final String QUEUE_URI = "/api/v1/queue";
    private final RabbitTemplate producerWithRoutingKey;
    @Autowired
    public RabbitMQIntegrationTest(RabbitTemplate producerWithRoutingKey) {
        this.producerWithRoutingKey = producerWithRoutingKey;
    }

    @Test
    void pushMessageToRabbitWhenHitEndPoint() {
        webTestClient.get()
                .uri(QUEUE_URI + "/send")
                .accept(MediaType.APPLICATION_JSON)
                .exchange()
                .expectStatus()
                .isOk();

        List<QueueMessage> messages = webTestClient.get()
                .uri(QUEUE_URI)
                .accept(MediaType.APPLICATION_JSON)
                .exchange()
                .expectStatus()
                .isOk()
                .expectBodyList(new ParameterizedTypeReference<QueueMessage>() {
                })
                .returnResult()
                .getResponseBody();

        assertThat(messages).isNotEmpty();
    }

    @Test
    void shouldGiveMessageWhenStoredMessageInDBThroughRabbitMQ() {
        String title = "Sending Message To Queue";
        String description = "We are testing the testContainer";

        SendMessage message = new SendMessage(title, description);

        producerWithRoutingKey
                .convertAndSend("testContainerExchange", "routing-key", message);

        List<QueueMessage> listMessages = webTestClient.get()
                .uri(QUEUE_URI)
                .accept(MediaType.APPLICATION_JSON)
                .exchange()
                .expectStatus()
                .isOk()
                .expectBodyList(new ParameterizedTypeReference<QueueMessage>() {
                })
                .returnResult()
                .getResponseBody();

        QueueMessage actualMessage = listMessages.stream()
                        .filter(m -> m.getTitle().equals(message.title()))
                        .findFirst()
                        .orElseThrow();

        assertThat(actualMessage.getTitle()).isEqualTo(message.title());
        assertThat(actualMessage.getDescription()).isEqualTo(message.description());
    }
}

当我分别运行这两个测试时,它们工作正常,因为我通过了,但是当我运行所有测试时,然后在第二个测试中 shouldGiveMessageWhenStoredMessageInDBThroughRabbitMQ() 中,我得到的 listMessage 为 null。

我不确定为什么会出现这种行为以及如何解决它?

java spring-boot rabbitmq testcontainers
1个回答
0
投票

在编写集成测试时,您遇到一个常见的挑战:由于共享状态,测试会相互干扰。在这种情况下,共享状态可能是 RabbitMQ 的消息队列、数据库或缓存。当您单独运行测试时,第一个测试的共享状态不会影响第二个测试。但是,当您一起运行它们时,第一个测试的剩余状态可能会干扰第二个测试。

所以我认为有一些关于如何解决您的问题的提示:

  1. 重置状态:在每次测试之前确保干净的状态,例如重置 RabbitMQ 队列。
  2. 新鲜的 RabbitMQ 实例:使用 TestContainers 为每个测试启动一个新鲜的 RabbitMQ 实例。
  3. 等待异步操作:RabbitMQ 是异步的。实现重试逻辑来等待消息,而不是仅仅期望立即可用。
  4. 检查测试设置:确保不存在命名错误等设置不一致的情况。
  5. 测试范围:使用 @WebFluxTest 或 @DataJpaTest 等注释缩小测试的 Spring 上下文。
  6. 使用@DirtiesContext:每次测试后重置Spring上下文以确保没有延迟状态。

注意,对于您提出的以下问题,请添加您正在测试的环境(即架构、操作系统和框架版本)。以便其他人可以重现您的问题并立即帮助您。

© www.soinside.com 2019 - 2024. All rights reserved.