我最近开始在我的Quarkus Web应用程序中使用testcontainers来进行单元/集成测试数据库操作。它可以很好地工作,但是我无法弄清楚如何在quarkus.datasource.url
的应用程序属性中动态设置MySQL端口。目前,我正在使用已弃用的withPortBindings
方法,强制容器将公开的MySQL端口绑定到端口11111,但正确的方法是让testcontainers选择一个随机的端口并覆盖quarkus.datasource.url
属性。
我的单元测试类
@Testcontainers
@QuarkusTest
public class UserServiceTest {
@Container
private static final MySQLContainer MY_SQL_CONTAINER = (MySQLContainer) new MySQLContainer()
.withDatabaseName("userServiceDb")
.withUsername("foo")
.withPassword("bar")
.withUrlParam("serverTimezone", "UTC")
.withExposedPorts(3306)
.withCreateContainerCmdModifier(cmd ->
((CreateContainerCmd) cmd).withHostName("localhost")
.withPortBindings(new PortBinding(Ports.Binding.bindPort(11111), new ExposedPort(3306))) // deprecated, let testcontainers pick random free port
);
@BeforeAll
public static void setup() {
// TODO: use the return value from MY_SQL_CONTAINER.getJdbcUrl()
// to set %test.quarkus.datasource.url
LOGGER.info(" ********************** jdbc url = {}", MY_SQL_CONTAINER.getJdbcUrl());
}
// snip...
}
我的 application.properties :
%test.quarkus.datasource.url=jdbc:mysql://localhost:11111/userServiceDb?serverTimezone=UTC
%test.quarkus.datasource.driver=com.mysql.cj.jdbc.Driver
%test.quarkus.datasource.username=foo
%test.quarkus.datasource.password=bar
%test.quarkus.hibernate-orm.dialect=org.hibernate.dialect.MySQL8Dialect
Quarkus 应用配置指南 介绍了如何以编程方式读取应用程序属性:
String databaseName = ConfigProvider.getConfig().getValue("database.name", String.class);
但并没有说明如何设置。使用测试容器和Quarkus的这个教程暗示它应该是可行的:
// 下面的代码不应该使用 - 函数已经弃用,并且为了测试简单起见,您应该在运行时覆盖属性
解决方案: 如建议中所述,我无须在数据源属性中指定主机和端口。因此,解决方案就是简单地替换application.properties中的两行代码:
%test.quarkus.datasource.url=jdbc:mysql://localhost:11111/userServiceDb
%test.quarkus.datasource.driver=com.mysql.cj.jdbc.Driver
使用
%test.quarkus.datasource.url=jdbc:tc:mysql:///userServiceDb
%test.quarkus.datasource.driver=org.testcontainers.jdbc.ContainerDatabaseDriver
(并且删除不必要的 withExposedPorts 和 withCreateContainerCmdModifier 方法调用)