Skip to content

Commit

Permalink
Merge pull request #25242 from snazy/doc-int-test-limits
Browse files Browse the repository at this point in the history
Document behavior of `@QuarkusIntegrationTest` w/ container networks
  • Loading branch information
gsmet authored May 9, 2022
2 parents 51ca57e + 3ccc084 commit a5d5bd1
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
41 changes: 39 additions & 2 deletions docs/src/main/asciidoc/getting-started-testing.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1209,7 +1209,7 @@ guide except injecting into tests (and the native executable runs in a separate
This is covered in the xref:building-native-image.adoc[Native Executable Guide].

[#quarkus-integration-test]
== Using @QuarkusIntegrationTest
== Using `@QuarkusIntegrationTest`

`@QuarkusIntegrationTest` should be used to launch and test the artifact produced by the Quarkus build, and supports testing a jar (of whichever type), a native image or container image.
Put simply, this means that if the result of a Quarkus build (`mvn package` or `gradle build`) is a jar, that jar will be launched as `java -jar ...` and tests run against it.
Expand Down Expand Up @@ -1281,18 +1281,28 @@ When `@QuarkusIntegrationTest` results in launching a container (because the app
This means that `@QuarkusIntegrationTest` works out of the box with containers launched via xref:dev-services.adoc[Dev Services], but it also means that it enables using <<quarkus-test-resource,QuarkusTestLifecycleManager>> resources that launch additional containers.
This can be achieved by having your `QuarkusTestLifecycleManager` implement `io.quarkus.test.common.DevServicesContext.ContextAware`. A simple example could be the following:

The container running the resource to test against, for example PostgreSQL via Testcontainers, is assigned an IP address from the container's network.
Use the container's "public" IP from its network and the "unmapped" port number to connect to the service.
The Testcontainers library usually return connection strings without respecting the container network, so additional code is needed to provide Quarkus the "correct" connection string using the container's IP on the container network and the _unmapped_ port number.

The following example illustrates the use with PostgreSQL, but the approach is applicable to all containers.

[source,java]
----
import io.quarkus.test.common.DevServicesContext;
import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
import org.testcontainers.containers.JdbcDatabaseContainer;
import org.testcontainers.containers.PostgreSQLContainer;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class CustomResource implements QuarkusTestResourceLifecycleManager, DevServicesContext.ContextAware {
private Optional<String> containerNetworkId;
private JdbcDatabaseContainer container;
@Override
public void setIntegrationTestContext(DevServicesContext context) {
Expand All @@ -1302,9 +1312,36 @@ public class CustomResource implements QuarkusTestResourceLifecycleManager, DevS
@Override
public Map<String, String> start() {
// start a container making sure to call withNetworkMode() with the value of containerNetworkId if present
container = new PostgreSQLContainer<>("postgres:latest").withLogConsumer(outputFrame -> {});
// apply the network to the container
containerNetworkId.ifPresent(container::withNetworkMode);
String jdbcUrl = container.getJdbcUrl();
if (containerNetworkId.isPresent()) {
// Replace hostname + port in the provided JDBC URL with the hostname of the Docker container
// running PostgreSQL and the listening port.
jdbcUrl = fixJdbcUrl(jdbcUrl);
}
// return a map containing the configuration the application needs to use the service
return new HashMap<>();
return ImmutableMap.of(
"quarkus.datasource.username", container.getUsername(),
"quarkus.datasource.password", container.getPassword(),
"quarkus.datasource.jdbc.url", jdbcUrl);
}
private String fixJdbcUrl(String jdbcUrl) {
// Part of the JDBC URL to replace
String hostPort = container.getHost() + ':' + container.getMappedPort(PostgreSQLContainer.POSTGRESQL_PORT);
// Host/IP on the container network plus the unmapped port
String networkHostPort =
container.getCurrentContainerInfo().getConfig().getHostName()
+ ':'
+ PostgreSQLContainer.POSTGRESQL_PORT;
return jdbcUrl.replace(hostPort, networkHostPort);
}
@Override
Expand Down
5 changes: 5 additions & 0 deletions docs/src/main/asciidoc/security-openid-connect.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,11 @@ Testing your `quarkus-oidc` `service` application with `OidcWiremockTestResource
If there is an immediate need for a test to define Wiremock stubs not currently supported by `OidcWiremockTestResource`
one can do so via a `WireMockServer` instance injected into the test class, for example:

[NOTE]
====
`OidcWiremockTestResource` does not work with `@QuarkusIntegrationTest` against Docker containers, because the Wiremock server is running in the JVM running the test, which cannot be accessed from the Docker container running the Quarkus application.
====

[source, java]
----
package io.quarkus.it.keycloak;
Expand Down

0 comments on commit a5d5bd1

Please sign in to comment.