如何在Docker容器内运行Spring Boot测试,贴近真实环境验证服务?
方案1:将Spring Boot服务作为普通Docker容器运行测试(推荐,复杂度低,完全满足生产环境模拟需求)
前置配置
- 先调整Gradle配置,确保测试执行前已构建好服务镜像:在build.gradle中添加
test.dependsOn dockerBuild,保证每次跑测试用的是最新代码构建的镜像。 - 所有依赖容器(PostgreSQL、Localstack)和服务容器需加入同一Docker网络,配置网络别名实现内部互通。
测试代码修改
你现有的测试类需要调整架构,去掉本地启动Spring Boot上下文的相关注解,改为启动容器化的服务,示例修改后的代码如下:
@Testcontainers @TestMethodOrder(OrderAnnotation.class) class MyApplicationTests { static DockerImageName localstackImage = DockerImageName.parse("localstack/localstack:0.11.3"); private static final LocalStackContainer.Service[] TEST_SERVICES = { LocalStackContainer.Service.SECRETSMANAGER, LocalStackContainer.Service.SSM, LocalStackContainer.Service.EC2, }; // 定义网络,所有容器加入该网络 static Network testNetwork = Network.newNetwork(); @Container static LocalStackContainer awsLocalStackContainers = new LocalStackContainer(localstackImage) .withServices(TEST_SERVICES) .withEnv("LOCALSTACK_HOSTNAME", "localstack") .withEnv("HOSTNAME", "localstack") .withNetwork(testNetwork) .withNetworkAliases("localstack"); // 网络别名,同网络内其他容器可通过该名称访问 @Container public static PostgreSQLContainer<?> postgreSQL = new PostgreSQLContainer<>("postgres:13.1") .withUsername("clusteradmin") .withPassword("testPassword") .withDatabaseName("public") .withNetwork(testNetwork) .withNetworkAliases("postgres"); // 数据库网络别名 // 定义Spring Boot服务容器,镜像名替换为你Palantir插件构建的实际镜像名 @Container static GenericContainer<?> appContainer = new GenericContainer<>("payouts-service:latest") .withNetwork(testNetwork) .withExposedPorts(8080) // 替换为你服务实际监听的端口 .dependsOn(postgreSQL, awsLocalStackContainers) // 依赖容器启动后再启服务 // 注入服务所需的所有配置,对应你原来的application-test.yml配置 .withEnv("SPRING_PROFILES_ACTIVE", "test,jpa") .withEnv("SPRING_DATASOURCE_URL", "jdbc:postgresql://postgres:5432/public") .withEnv("SPRING_DATASOURCE_USERNAME", "clusteradmin") .withEnv("SPRING_DATASOURCE_PASSWORD", "testPassword") .withEnv("AWS_SECRETSMANAGER_ENDPOINT", "http://localstack:4566") .withEnv("AWS_SSM_ENDPOINT", "http://localstack:4566") .withEnv("AWS_REGION", awsLocalStackContainers.getRegion()) .withEnv("aws.paramstore.enabled", "false") .withEnv("aws.secretsmanager.enabled", "false") // 你需要排除的Spring Cloud AWS自动配置也可以通过环境变量注入,或者直接写在测试配置文件里 .withEnv("SPRING_AUTOCONFIGURE_EXCLUDE", "org.springframework.cloud.aws.autoconfigure.context.ContextInstanceDataAutoConfiguration,org.springframework.cloud.aws.autoconfigure.context.ContextStackAutoConfiguration,org.springframework.cloud.aws.autoconfigure.context.ContextRegionProviderAutoConfiguration"); // 测试用例示例:通过映射端口访问容器内的服务 @Test void testServiceHealth() { String baseUrl = "http://" + appContainer.getHost() + ":" + appContainer.getMappedPort(8080); RestTemplate restTemplate = new RestTemplate(); String healthRes = restTemplate.getForObject(baseUrl + "/actuator/health", String.class); // 断言验证返回结果 Assertions.assertNotNull(healthRes); } }
注意事项
- 你原来的PropertiesListener逻辑如果需要注入Localstack客户端,不需要再用反射注入,直接在Localstack容器启动后调用对应API往Secret Manager、SSM里写入测试数据即可,服务启动后会自动从Localstack读取。
- 如果需要传递更多配置,直接通过
withEnv方法注入环境变量即可,和生产环境容器运行的参数传递方式完全一致。
方案2:在Localstack EC2实例中运行服务测试(仅当需要验证EC2内运行逻辑时使用,复杂度较高)
- 服务镜像构建完成后,调用Localstack的EC2 API将镜像导入到Localstack的镜像仓库中
- 调用EC2 RunInstances接口启动实例,指定使用导入的服务镜像,配置实例安全组开放服务端口
- 通过Localstack的EC2公网IP映射访问服务,执行测试逻辑
该方案需要额外编写EC2操作的工具代码,常规测试不需要用到,方案1已经可以100%模拟生产容器运行环境。
内容的提问来源于stack exchange,提问作者MrkK
相关产品推荐
相关产品推荐

