
本教程旨在解决在Testcontainers集成测试中,非Spring Java应用如何动态获取并使用PostgreSQL数据库容器的连接信息。核心方法是通过Testcontainers的网络功能和依赖管理,使应用容器与数据库容器在同一网络中通信,并利用网络别名和固定端口构建JDBC URL,从而避免了静态属性文件和Spring `@DynamicPropertySource`的限制。
在Java应用的集成测试中,Testcontainers提供了一种便捷的方式来启动真实的服务(如数据库、消息队列等)作为Docker容器。然而,对于不使用Spring框架的应用,当需要在测试运行时动态获取这些容器的连接信息(例如JDBC URL)并将其注入到应用容器中时,会遇到一些挑战。
典型的场景是:一个Java应用需要连接PostgreSQL数据库。在Testcontainers测试中,我们可能启动一个PostgreSQL容器和一个应用容器。问题在于,PostgreSQL容器启动后才能确定其JDBC URL(尤其是随机映射的端口),而应用容器可能需要这个URL才能正确启动。如果应用依赖于一个静态的datasource.properties文件,并且该文件需要在PostgreSQL容器启动后动态生成,那么应用容器的启动时机就成了一个问题。对于非Spring应用,也无法利用Spring Boot的@DynamicPropertySource注解来动态注入属性。
本文将介绍一种基于Testcontainers原生网络和依赖管理机制的解决方案,以优雅地解决这一问题。
解决上述问题的关键在于Testcontainers提供的两大功能:容器网络和容器依赖。
结合这两点,我们可以让应用容器在PostgreSQL容器启动后,通过一个预定义的网络别名和标准端口来访问数据库,从而无需动态生成和加载属性文件。
以下是如何在Testcontainers中实现这一策略的详细步骤和示例代码:
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.utility.DockerImageName;
public class ApplicationIntegrationTest {
public static void main(String[] args) {
// 1. 创建一个共享的Docker网络
Network network = Network.newNetwork();
// 2. 启动PostgreSQL数据库容器
// - 指定Docker镜像
// - 将其连接到共享网络
// - 设置网络别名,应用容器将通过此别名访问数据库
PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>(DockerImageName.parse("postgres:15"))
.withNetwork(network)
.withNetworkAliases("postgres"); // 数据库在网络中的别名
// 3. 启动应用容器
// - 指定Docker镜像
// - 将其连接到共享网络
// - 暴露应用端口(如果需要外部访问)
// - 声明对PostgreSQL容器的依赖,确保数据库先启动
// - 通过环境变量将JDBC URL注入到应用容器中
GenericContainer<?> app = new GenericContainer<>(DockerImageName.parse("my-app:0.0.1"))
.withNetwork(network)
.withExposedPorts(8080) // 假设应用暴露8080端口
.dependsOn(postgres)
// 关键:在应用容器启动前,通过环境变量传递JDBC URL
// 应用内部需要配置为从这个环境变量读取数据库连接信息
.withEnv("JDBC_URL", "jdbc:postgresql://postgres:5432/test")
.withEnv("DB_USERNAME", postgres.getUsername()) // 也可以传递用户名
.withEnv("DB_PASSWORD", postgres.getPassword()); // 也可以传递密码
// 4. 启动容器
// 由于设置了dependsOn,Testcontainers会确保postgres先启动
postgres.start();
app.start();
// 此时,应用容器已启动,并且能够通过 "jdbc:postgresql://postgres:5432/test" 访问数据库。
// 你可以在这里执行你的集成测试逻辑,例如:
// RestAssured.given().port(app.getMappedPort(8080)).get("/health").then().statusCode(200);
// 5. 测试结束后,停止容器
// app.stop();
// postgres.stop();
// network.close(); // 关闭网络
}
}代码解析:
通过利用Testcontainers的容器网络和依赖管理功能,我们为非Spring Java应用提供了一种健壮且灵活的方式来在集成测试中动态连接数据库容器。这种方法避免了传统静态属性文件的限制,也无需依赖Spring框架特定的动态属性机制。通过将容器置于同一网络并使用网络别名,以及通过环境变量注入连接信息,我们可以构建出更可靠、更真实的集成测试环境。
以上就是Testcontainers中非Spring应用动态加载数据库连接属性的教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号