

Quarkus and Testcontainers
source link: https://www.morling.dev/blog/quarkus-and-testcontainers/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Quarkus and Testcontainers
The Testcontainers project is invaluable for spinning up containerized resources during your (JUnit) tests, e.g. databases or Kafka clusters.
For users of JUnit 5, the project provides the @Testcontainers
extension, which controls the lifecycle of containers used by a test.
When testing a Quarkus application though, this is at odds with Quarkus' own @QuarkusTest
extension;
it’s a recommended best practice to avoid fixed ports for any containers started by Testcontainers.
Instead, you should rely on Docker to automatically allocate random free ports.
This avoids conflicts between concurrently running tests,
e.g. amongst multiple Postgres containers,
started up by several parallel job runs in a CI environment, all trying to allocate Postgres' default port 5432.
Obtaining the randomly assigned port and passing it into the Quarkus bootstrap process isn’t possible though when combining the two JUnit extensions.
One work-around you can find described e.g. on StackOverflow is setting up the database container via a static class initializer block and then propagating the host and port to Quarkus through system properties. While this works, it’s not ideal in terms of lifecycle control (e.g. how to make sure the container is started up once at the beginning of an entire test suite), and in general, it just feels a bit hack-ish.
Luckily, there’s a better alternative, which interestingly isn’t discussed as much:
using Quarkus' notion of test resources.
There’s just two steps involved.
First, create an implementation of the QuarkusTestResourceLifecycleManager
interface,
which controls your resource’s lifecycle.
In case of a Postgres database, this could look like this:
public class PostgresResource implements
QuarkusTestResourceLifecycleManager {
static PostgreSQLContainer<?> db =
new PostgreSQLContainer<>("postgres:13") (1)
.withDatabaseName("tododb")
.withUsername("todouser")
.withPassword("todopw");
@Override
public Map<String, String> start() { (2)
db.start();
return Collections.singletonMap(
"quarkus.datasource.url", db.getJdbcUrl()
);
}
@Override
public void stop() { (3)
db.stop();
}
}
All you then need to do is to reference that test resource from your test class using the @QuarkusTestResource
annotation:
@QuarkusTest
@QuarkusTestResource(PostgresResource.class) (1)
public class TodoResourceTest {
@Test
public void createTodoShouldYieldId() {
given()
.when()
.contentType(ContentType.JSON)
.body("""
{
"title" : "Learn Quarkus",
"priority" : 1,
}
""")
.then()
.statusCode(201)
.body(
matchesJson(
"""
{
"id" : 1,
"title" : "Learn Quarkus",
"priority" : 1,
"completed" : false,
}
"""));
}
}
And that’s it! Note that all the test resources of the test module are detected and started up, before starting the first test.
Bonus: Schema Creation
One other subtle issue is the creation of the database schema for the test. E.g. for my Todo example application, I’d like to use a schema named "todo" in the Postgres database:
create schema todo;
Quarkus supports SQL load scripts for executing SQL scripts when Hibernate ORM starts.
But this will be executed only after Hibernate ORM has set up all the database objects,
such as tables, sequences, indexes etc.
(I’m using the drop-and-create
database generation mode during testing).
This means that while a load script is great for inserting test data,
it’s executed too late for defining the actual database schema itself.
Luckily, most database container images themselves support the execution of load scripts right upon database start-up; The Postgres image is no exception, so it’s just a matter of exposing that script via Testcontainers. All it needs for that is a bit of tweaking of the Quarkus test resource for Postgres:
static PostgreSQLContainer<?> db =
new PostgreSQLContainer<>("postgres:13")
.withDatabaseName("tododb")
.withUsername("todouser")
.withPassword("todopw")
.withClasspathResourceMapping("init.sql", (1)
"/docker-entrypoint-initdb.d/init.sql",
BindMode.READ_ONLY);
With that in place, Postgres will start up and the "todo" schema will be created in the database, before Quarkus boots Hibernate ORM, which will populate the schema, and finally, all tests can run.
You can find the complete source code of this test and the Postgres test resource on GitHub.
Many thanks to Sergei Egorov for his feedback while writing this blog post!
Recommend
-
27
Testcontainers is a Golang library that providing a friendly API to run Docker container. It is designed to create runtime environment to use during your automatic tests.
-
43
README.md Testcontainers Testcontainers is a Java 8 library that supports JUnit tests, providing lightweight, throwaway instances of commo...
-
10
Blogs Configuring Podman for Quarkus Dev Services and Testcontainers on Linux Configuring Podman for Quar...
-
10
Quarkus Dev Services, jOOQ, Flyway, and Testcontainers: A Full Example Wednesday, April 20, 2022 I have written a few posts about...
-
8
Testcontainers With Kotlin and Spring Data R2DBC In this article we are going...
-
4
It has been some time since we published an update on Testcontainers for Go, and it’s time to share the recent updates in terms of Community and functionality with you.We strongly believe in Open Source; and with that, community comes first....
-
2
Developing resilient applications with Toxiproxy and Testcontainers Skip to main conte...
-
7
In this guide, you will learn how toCreate a Spring Boot application with jOOQ supportGenerate jOOQ code using Testcontainers, Flyway and Maven PluginImplement basic database operation...
-
3
Joyful Quarkus Application Development using Testcontainers Desktop Quarkus is one of the most popular frameworks in the JVM ecosystem that revolutionized the way developers crea...
-
6
December 12, 2023 Testing Typesense search with Testcontainers and .NET
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK