SpringBootTest与WebTestClient批量执行测试返回409冲突问题
解决SpringBootTest集成测试批量运行返回409的问题
你遇到的问题根本不是端口的锅——虽然你用了RANDOM_PORT,但同一个测试类里的所有测试方法会共享同一个Spring应用上下文和数据库数据。看你的代码,第二个测试直接调用了第一个带@Test的方法,当批量运行整个类时:
- 第一个测试先执行,创建了索引;
- 第二个测试执行时,又调用了一次创建索引的逻辑,此时索引已经存在,接口自然返回409(冲突);
而单独运行单个测试时,没有之前的数据残留,所以返回正常的201/200。
解决方案
- 让测试方法完全独立:不要在一个测试方法里调用另一个带
@Test的方法。把公共逻辑(比如创建索引)抽成普通方法,每个测试按需调用。 - 用事务回滚隔离数据:给测试类或测试方法添加
@Transactional注解,Spring会在每个测试执行完毕后自动回滚事务,保证每个测试的数据库环境都是干净的。 - 手动清理数据:如果事务不适用(比如用了非关系型数据库),可以用
@BeforeEach/@AfterEach注解的方法,在每个测试前后清空相关数据。
修改后的代码示例(事务隔离版)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @Transactional // 自动回滚每个测试的事务 class ControllerTest { @Autowired private WebTestClient webTestClient; // 抽公共创建逻辑,不要加@Test注解 private void createIndex() { CreationInputDto input = new CreationInputDto(); webTestClient .post() .uri("/create") .body(Mono.just(input), CreationInputDto.class) .exchange() .expectStatus().isEqualTo(201); } @Test void happyPath_createIndex() { createIndex(); } @Test void happyPath_adjustIndex_additionOperation() { createIndex(); // 调用公共方法,而非另一个测试方法 AdjustmentInputDto input = new AdjustmentInputDto(); webTestClient .post() .uri("/indexAdjustment") .body(Mono.just(input), AdjustmentInputDto.class) .exchange() .expectStatus().isEqualTo(201); } }
手动清理数据版(非关系型数据库适用)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class ControllerTest { @Autowired private WebTestClient webTestClient; @Autowired private IndexRepository indexRepository; // 假设你的数据访问层 // 每个测试前清空数据 @BeforeEach void setUp() { indexRepository.deleteAll(); } @Test void happyPath_createIndex() { CreationInputDto input = new CreationInputDto(); webTestClient .post() .uri("/create") .body(Mono.just(input), CreationInputDto.class) .exchange() .expectStatus().isEqualTo(201); } @Test void happyPath_adjustIndex_additionOperation() { // 自己完成前置创建操作 CreationInputDto createInput = new CreationInputDto(); webTestClient .post() .uri("/create") .body(Mono.just(createInput), CreationInputDto.class) .exchange() .expectStatus().isEqualTo(201); // 执行调整操作 AdjustmentInputDto input = new AdjustmentInputDto(); webTestClient .post() .uri("/indexAdjustment") .body(Mono.just(input), AdjustmentInputDto.class) .exchange() .expectStatus().isEqualTo(201); } }
内容的提问来源于stack exchange,提问作者Bahar
相关产品推荐
相关产品推荐

