使用Testcontainers和PostgreSQL的Quarkus测试(详细指南)

945 阅读6分钟

Testcontainers是一个Java库,允许在JUnit测试中轻松集成Docker容器。在一个容器化的世界里,用嵌入式数据库和服务使测试配置复杂化是没有意义的。相反,在Docker中运行你的服务,让Testcontainers为你管理这些。因此,如果你在测试中需要Redis、MongoDB或PostgreSQL - Testcontainers可能成为你的好朋友。

在这篇博文中,你将学习如何配置Testcontainers来管理Quarkus集成测试中的PostgreSQL实例。

目录

依赖关系

为了在PostgreSQL中使用Testcontainers,你需要在pom.xml 中添加以下依赖项:

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>testcontainers</artifactId>
    <version>1.12.5</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>postgresql</artifactId>
    <version>1.12.5</version>
    <scope>test</scope>
</dependency>

注意:Testcontainers提供JUnit 5插件,但在本文介绍的方案中不需要。

测试数据源配置

Quarkus应用程序中默认的PostgreSQL配置可能看起来如下:

quarkus.datasource.url=jdbc:postgresql://localhost:5432/some-db
quarkus.datasource.driver=org.postgresql.Driver
quarkus.datasource.username=user
quarkus.datasource.password=password

默认情况下,这个配置将被用于任何活动的配置文件。Quarkus中内置的配置文件是。dev,prodtesttest 配置文件将在你每次运行@QuarkusTest 的时候被使用。

你可以通过在src/main/application.properties 文件的配置属性中提供%test. 的前缀来调整test 配置文件。这允许通过JDBC URL方案来配置(和启动)PostgreSQL数据库容器。为了达到这个目的,请确保:

  • 将驱动程序设置为org.testcontainers.jdbc.ContainerDatabaseDriver 。这个特殊的驱动程序可以确保一旦我们在应用程序中需要数据源,Docker容器就会被创建和运行。
  • 将方言明确设置为org.hibernate.dialect.PostgreSQL9Dialect ,否则在启动应用程序时就会出现异常。
org.junit.jupiter.api.extension.TestInstantiationException: TestInstanceFactory [io.quarkus.test.junit.QuarkusTestExtension] failed to instantiate test class [pl.codeleak.samples.OwnerResourceTest]: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
 [error]: Build step io.quarkus.hibernate.orm.deployment.HibernateOrmProcessor#build threw an exception: io.quarkus.deployment.configuration.ConfigurationError: Hibernate extension could not guess the dialect from the driver 'org.testcontainers.jdbc.ContainerDatabaseDriver'. Add an explicit 'quarkus.hibernate-orm.dialect' property.
 at io.quarkus.hibernate.orm.deployment.HibernateOrmProcessor.guessDialect(HibernateOrmProcessor.java:715)
  • 将JDBC URL设置为jdbc:tc:postgresql:latest:///dbname ,这样Testcontainers就知道在运行容器时要使用哪个PostgreSQL版本。

完整的配置:

# initializes container for driver initialization
%test.quarkus.datasource.driver=org.testcontainers.jdbc.ContainerDatabaseDriver

# dialect must be set explicitly
%test.quarkus.hibernate-orm.dialect=org.hibernate.dialect.PostgreSQL9Dialect

# Testcontainers JDBC URL
%test.quarkus.datasource.url=jdbc:tc:postgresql:latest:///dbname

配置到位后,你可以运行测试,观察测试容器是否为测试而创建:


$ ./mvnw clean test

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running pl.codeleak.samples.OwnerResourceTest
2020-02-27 21:09:21,096 INFO  [io.qua.fly.FlywayProcessor] (build-8) Adding application migrations in path '/Users/rafal.borowiec/Projects/quarkus/quarkus-postgres-sample/target/classes/db/migration' using protocol 'file'
2020-02-27 21:09:23,084 INFO  [org.fly.cor.int.lic.VersionPrinter] (main) Flyway Community Edition 6.1.4 by Redgate
2020-02-27 21:09:23,176 INFO  [org.tes.doc.DockerClientProviderStrategy] (Agroal_1012722761) Loaded org.testcontainers.dockerclient.UnixSocketClientProviderStrategy from ~/.testcontainers.properties, will try it first
2020-02-27 21:09:23,658 INFO  [org.tes.doc.UnixSocketClientProviderStrategy] (Agroal_1012722761) Accessing docker with local Unix socket
2020-02-27 21:09:23,659 INFO  [org.tes.doc.DockerClientProviderStrategy] (Agroal_1012722761) Found Docker environment with local Unix socket (unix:///var/run/docker.sock)
2020-02-27 21:09:23,780 INFO  [org.tes.DockerClientFactory] (Agroal_1012722761) Docker host IP address is localhost
2020-02-27 21:09:23,815 INFO  [org.tes.DockerClientFactory] (Agroal_1012722761) Connected to docker:
  Server Version: 19.03.2
  API Version: 1.40
  Operating System: Docker Desktop
  Total Memory: 1998 MB
2020-02-27 21:09:23,957 INFO  [org.tes.uti.RegistryAuthLocator] (Agroal_1012722761) Credential helper/store (docker-credential-desktop) does not have credentials for quay.io
2020-02-27 21:09:24,857 INFO  [org.tes.DockerClientFactory] (Agroal_1012722761) Ryuk started - will monitor and terminate Testcontainers containers on JVM exit
2020-02-27 21:09:24,857 INFO  [org.tes.DockerClientFactory] (Agroal_1012722761) Checking the system...
2020-02-27 21:09:24,858 INFO  [org.tes.DockerClientFactory] (Agroal_1012722761) ✔︎ Docker server version should be at least 1.6.0
2020-02-27 21:09:25,040 INFO  [org.tes.DockerClientFactory] (Agroal_1012722761) ✔︎ Docker environment should have more than 2GB free disk space
2020-02-27 21:09:25,078 INFO  [🐳 [postgres:latest]] (Agroal_1012722761) Creating container for image: postgres:latest
2020-02-27 21:09:25,135 INFO  [org.tes.uti.RegistryAuthLocator] (Agroal_1012722761) Credential helper/store (docker-credential-desktop) does not have credentials for index.docker.io
2020-02-27 21:09:25,247 INFO  [🐳 [postgres:latest]] (Agroal_1012722761) Starting container with ID: b436fdabccbe51ba3e6d778d4429505473995d4185a200aef35c4c30b2159369
2020-02-27 21:09:25,779 INFO  [🐳 [postgres:latest]] (Agroal_1012722761) Container postgres:latest is starting: b436fdabccbe51ba3e6d778d4429505473995d4185a200aef35c4c30b2159369
2020-02-27 21:09:26,896 INFO  [🐳 [postgres:latest]] (Agroal_1012722761) Container postgres:latest started in PT3.731519S
2020-02-27 21:09:27,107 INFO  [org.fly.cor.int.dat.DatabaseFactory] (main) Database: jdbc:postgresql://localhost:32830/test (PostgreSQL 12.2)
2020-02-27 21:09:27,146 INFO  [org.fly.cor.int.sch.JdbcTableSchemaHistory] (main) Creating Schema History table "public"."flyway_schema_history" ...
2020-02-27 21:09:27,188 INFO  [org.fly.cor.int.com.DbMigrate] (main) Current version of schema "public": << Empty Schema >>
2020-02-27 21:09:27,193 INFO  [org.fly.cor.int.com.DbMigrate] (main) Migrating schema "public" to version 1.0.0 - Init
2020-02-27 21:09:27,201 INFO  [org.fly.cor.int.sql.DefaultSqlScriptExecutor] (main) DB: table "owners" does not exist, skipping
2020-02-27 21:09:27,226 INFO  [org.fly.cor.int.com.DbMigrate] (main) Successfully applied 1 migration to schema "public" (execution time 00:00.050s)
2020-02-27 21:09:27,726 INFO  [io.quarkus] (main) Quarkus 1.2.1.Final started in 5.761s. Listening on: http://0.0.0.0:8081
2020-02-27 21:09:27,727 INFO  [io.quarkus] (main) Profile test activated.
2020-02-27 21:09:27,727 INFO  [io.quarkus] (main) Installed features: [agroal, cdi, flyway, hibernate-orm, hibernate-orm-panache, hibernate-validator, jdbc-postgresql, narayana-jta, resteasy, resteasy-jackson]
[INFO] Tests run: 10, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 10.091 s - in pl.codeleak.samples.OwnerResourceTest
2020-02-27 21:09:29,975 INFO  [io.quarkus] (main) Quarkus stopped in 0.689s
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 10, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  15.375 s
[INFO] Finished at: 2020-02-27T21:09:30+01:00
[INFO] ------------------------------------------------------------------------

请看这里的官方文档中关于数据库配置的更多内容: https://www.testcontainers.org/modules/databases/

初始化测试数据库

你有几个选项来初始化数据库。你可以用Flyway 来初始化数据库,但你也可以使用Testcontainers在数据库启动后但在连接返回到代码前运行init脚本。

使用Flyway来初始化测试数据库

使用Flyway,迁移脚本可以只针对测试配置文件进行调整,就像我们调整数据源一样--通过在配置属性中添加%test. 前缀。这样你就可以设置不同的迁移文件位置和/或可以为迁移文件配置不同的前缀。

%test.quarkus.flyway.locations=test_db/migration
%test.quarkus.flyway.sql-migration-prefix=test_

在上述配置下,你可能需要创建test/src/resources/test_db/migration ,并在其中放入例如test_1.0.0_schema.sql 文件(名称模式为test_version_description.sql )。

提示:不要忘记在pom.xml 中添加Flyway Quarkus扩展。

使用Testcontainers来初始化测试数据库

如果你不想在测试中使用Flyway,你可以用Testcontainers加载的脚本来初始化数据库。该文件可以直接从classpath加载,也可以从任何位置加载。唯一要做的就是改变JDBC的URL:

%test.quarkus.datasource.url=jdbc:tc:postgresql:latest:///dbname?TC_INITSCRIPT=file:src/main/resources/init_pg.sql

%test.quarkus.datasource.url=jdbc:tc:postgresql:latest:///dbname?TC_INITSCRIPT=classpath:init_pg.sql

源代码

本文的源代码可以在Github上找到:https://github.com/kolorobot/quarkus-postgres-sample(testcontainers branch)

另见