Spring Boot 3 + Testcontainers集成测试被忽略无明确错误求助
解决Testcontainers + @ServiceConnection集成测试被跳过的问题
问题描述
使用MySQLContainer和@ServiceConnection运行Spring Boot集成测试时,JUnit直接将测试标记为“ignored/skipped”,核心报错日志如下:
java.lang.IllegalStateException: Could not find a valid Docker environment. Please see logs and check configuration at org.testcontainers.dockerclient.DockerClientProviderStrategy.lambda$getFirstValidStrategy$7(DockerClientProviderStrategy.java:274) ... Suppressed: org.testcontainers.containers.ContainerFetchException: Can't get Docker image: RemoteDockerImage(imageName=mysql:8.4, ...) ...
修复步骤
1. 统一Testcontainers依赖版本
你的Testcontainers组件版本不匹配:junit-jupiter用了1.20.5,testcontainers-mysql却用了2.0.1,版本冲突会导致Docker连接逻辑异常。修改pom.xml,将所有Testcontainers依赖统一到同一版本:
<!-- 统一Testcontainers版本 --> <dependency> <groupId>org.testcontainers</groupId> <artifactId>junit-jupiter</artifactId> <version>1.20.5</version> <scope>test</scope> </dependency> <dependency> <groupId>org.testcontainers</groupId> <artifactId>mysql</artifactId> <!-- 注意:正确的artifactId是mysql,不是testcontainers-mysql --> <version>1.20.5</version> <scope>test</scope> </dependency>
2. 移除冲突的数据源配置
你同时启用了两种Testcontainers配置方式,二者会互相干扰:
- 代码中的
@Container + @ServiceConnection注解 - application-test.yml中的
jdbc:tc:mysql:8.4:///testdb配置
二选一即可解决冲突:
方案A:保留@ServiceConnection方式
直接删除application-test.yml中的spring.datasource配置段,让@ServiceConnection自动接管数据源配置。
方案B:保留TC JDBC URL方式
删除代码中的@Container和@ServiceConnection注解,依赖Testcontainers JDBC驱动自动启动容器。此时application-test.yml的配置无需修改,但要确保mysql-connector-j依赖存在。
3. 验证Docker环境可用性
- 确认Docker Desktop(Windows/macOS)或Docker服务(Linux)处于运行状态
- Linux用户需确保当前用户属于
docker组,执行以下命令后重新登录:sudo usermod -aG docker $USER - 执行
docker ps命令验证是否能正常连接Docker,无权限报错则环境正常。
4. 调整Java版本(可选)
你使用的Java 25是非LTS版本,Testcontainers 1.20.5对其兼容性可能存在隐患。建议降级到稳定LTS版本(如Java 21),避免潜在的兼容性问题。
修改后的测试类(核心逻辑无需改动)
@Testcontainers @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class ArtistControllerIT { @Autowired private TestRestTemplate testRestTemplate; @Container @ServiceConnection private static final MySQLContainer container = new MySQLContainer("mysql:8.0"); @LocalServerPort private int port; @Autowired private ArtistRepository artistRepository; @Test @DisplayName("List returns list of artist inside page object when successful") void list_ReturnsListOfArtistInsidePageObjet_WhenSuccessful() { Artist saved = artistRepository.save(ArtistCreator.createArtistToBeSaved()); PageableResponse<Artist> artistPage = testRestTemplate.exchange( "/artists/list-artists", HttpMethod.GET, null, new ParameterizedTypeReference<PageableResponse<Artist>>() {} ).getBody(); assertThat(artistPage).isNotNull(); assertThat(artistPage.getContent()).hasSize(1); assertThat(artistPage.getContent().get(0).getName()).isEqualTo(saved.getName()); } @Test @DisplayName("Should return an artist dto by id when found one") void shouldReturnAnArtist_WhenPassedId() { Artist saved = artistRepository.save(ArtistCreator.createValidArtist()); testRestTemplate.exchange("/artists", HttpMethod.GET, null, saved.getClass(), saved.getId()); assertEquals(1L, saved.getId(), "ID SHOULD BE 1"); } }
内容的提问来源于stack exchange,提问作者user32684286
相关产品推荐
相关产品推荐

