Spring Boot集成Test Containers测试失败:UnknownHostException(app_db)
问题:TestContainers集成测试连接
app_db失败(UnknownHostException) 我基于Spring Boot + MySQL + Docker + Flyway实现了一个项目,使用Test Containers编写集成测试类时,程序始终尝试连接docker-compose中定义的app_db主机,抛出java.net.UnknownHostException: No such host is known (app_db)异常。以下是相关代码和配置:
测试类代码
@Testcontainers @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) public class UserControllerIntegrationTest { @Autowired private UserController userController; @Autowired UriComponentsBuilder builder; @Container public static MySQLContainer container = new MySQLContainer("mysql:latest") .withDatabaseName("example_db") .withUsername("Test") .withPassword("Test"); @Container public static GenericContainer<?> redis = new GenericContainer<>(DockerImageName.parse("redis:6.2-alpine")).withExposedPorts(6379); @BeforeAll public static void setUp(){ container.withReuse(true); container.withInitScript("src/main/test/resources/schema.sql"); container.start(); redis.start(); } @DynamicPropertySource public static void overrideProperties(DynamicPropertyRegistry registry){ registry.add("spring.datasource.url", container::getJdbcUrl); registry.add("spring.datasource.username", container::getUsername); registry.add("spring.datasource.password", container::getPassword); registry.add("spring.datasource.driver-class-name", container::getDriverClassName); } @Test public void testCreateUser(){ CreateUserRequestDto request = new CreateUserRequestDto(); request.setName("Test User"); request.setAge(45); UserResponseDto response = userController.create(request); assertNotNull(response); } }
docker-compose.yml配置
version: "3.0" services: api_service: build: . restart: always ports: - 8090:8090 depends_on: - mysql_db links: - mysql_db:app_db mysql_db: image: "mysql:8.0" restart: always ports: - 3306:3306 environment: MYSQL_DATABASE: test_db MYSQL_USER: user MYSQL_PASSWORD: password MYSQL_ROOT_PASSWORD: password
application.yml配置
app: name: test-service server: port: 8090 spring: datasource: url: jdbc:mysql://app_db:3306/test_db username: user password: password initialization-mode: always jpa: properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect hibernate: ddl-auto: create
报错信息
Caused by: java.net.UnknownHostException: No such host is known (app_db)
解决方法
核心原因
测试代码中虽然通过@DynamicPropertySource尝试覆盖数据源配置,但因容器生命周期管理错误、配置加载顺序冲突,导致application.yml中app_db的原始配置未被正确覆盖,程序仍尝试连接docker-compose专属的内部主机名。
具体修复步骤
1. 修正TestContainers容器初始化逻辑
@Testcontainers注解会自动管理容器的启动/停止,手动调用start()会导致重复初始化,干扰动态属性注入:
- 删除
@BeforeAll方法,移除手动启动容器的代码 - 将
withReuse(true)和withInitScript直接放在容器实例化时配置,同时用classpath路径替代绝对路径,提高兼容性:@Container public static MySQLContainer container = new MySQLContainer("mysql:latest") .withDatabaseName("example_db") .withUsername("Test") .withPassword("Test") .withReuse(true) .withInitScript("classpath:schema.sql"); @Container public static GenericContainer<?> redis = new GenericContainer<>(DockerImageName.parse("redis:6.2-alpine")) .withExposedPorts(6379);
2. 补全动态属性覆盖(含Flyway)
如果项目使用Flyway,它会独立读取数据源配置,需要一起覆盖:
@DynamicPropertySource public static void overrideProperties(DynamicPropertyRegistry registry){ registry.add("spring.datasource.url", container::getJdbcUrl); registry.add("spring.datasource.username", container::getUsername); registry.add("spring.datasource.password", container::getPassword); registry.add("spring.datasource.driver-class-name", container::getDriverClassName); // 覆盖Flyway配置(如果使用了Flyway) registry.add("spring.flyway.url", container::getJdbcUrl); registry.add("spring.flyway.user", container::getUsername); registry.add("spring.flyway.password", container::getPassword); // 覆盖Redis配置(如果需要使用Redis) registry.add("spring.redis.host", redis::getHost); registry.add("spring.redis.port", redis::getFirstMappedPort); }
3. 为测试环境单独配置
创建src/test/resources/application-test.yml,隔离测试与生产配置:
spring: datasource: initialization-mode: never # 禁用默认初始化,改用TestContainers的initScript jpa: hibernate: ddl-auto: none # 避免与Flyway的Schema管理冲突 flyway: enabled: true # 按需开启
然后在测试类上添加@ActiveProfiles("test"),指定使用测试配置:
@Testcontainers @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) @ActiveProfiles("test") // 添加该注解 public class UserControllerIntegrationTest { // ... 其他代码 }
4. 验证Docker运行状态
确保本地Docker daemon处于运行状态,TestContainers能正常创建和管理容器。
内容的提问来源于stack exchange,提问作者Lakshitha Gihan
相关产品推荐
相关产品推荐

