mirror of
https://github.com/docker/docs.git
synced 2026-03-28 23:08:49 +07:00
## Description Migrate 17 Testcontainers guides from testcontainers.com into the Docker docs site, covering Java (14 guides), .NET (2 guides), and Node.js (1 guide). This follows up on PR #24450 which added the initial Go and Python guides. Each guide is converted from AsciiDoc to Hugo Markdown, split into multi-chapter stepper navigation, updated to the latest Testcontainers API, and verified with passing tests running in containers. Java guides use testcontainers-java 2.0.4 with the new 2.x Maven coordinates and package names (e.g., `testcontainers-postgresql`, `org.testcontainers.postgresql.PostgreSQLContainer`). The Quarkus guide uses Quarkus 3.22.3 with TC 1.x managed by the Quarkus BOM, since no released Quarkus version ships TC 2.x yet. ## How to test All code snippets have been verified by running each guide's source repository tests inside Docker containers with the Docker socket mounted. To re-run the verification, use the `/testcontainers-guides-migrator` skill included in this PR (`.claude/skills/testcontainers-guides-migrator/SKILL.md`). The skill's Step 6 documents the exact container commands and macOS Docker Desktop workarounds (host override, docker-java API version, etc.) needed to run each language's tests: ``` /testcontainers-guides-migrator I want you to verify all the guides in this branch. Do a full review, verifying that all code snippets compile, the code is executable, and ALL the tests pass. Run them as docker containers, never locally. ``` ## Related issues or tickets Supersedes #24450 (expanded from 2 guides to all 19) ## Reviews - [ ] Technical review - [ ] Editorial review - [ ] Product review --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
186 lines
6.1 KiB
Markdown
186 lines
6.1 KiB
Markdown
---
|
|
title: Write tests with Testcontainers
|
|
linkTitle: Write tests
|
|
description: Test the Quarkus REST API using Dev Services with Testcontainers, and test with services not supported by Dev Services.
|
|
weight: 20
|
|
---
|
|
|
|
## Quarkus Dev Services
|
|
|
|
Quarkus Dev Services automatically provisions unconfigured services in
|
|
development and test mode. When you include an extension and don't configure it,
|
|
Quarkus starts the relevant service using
|
|
[Testcontainers](https://www.testcontainers.org/) behind the scenes and wires
|
|
the application to use that service.
|
|
|
|
> [!NOTE]
|
|
> Dev Services requires a
|
|
> [supported Docker environment](https://www.testcontainers.org/supported_docker_environment/).
|
|
|
|
Quarkus Dev Services supports most commonly used services like SQL databases,
|
|
Kafka, RabbitMQ, Redis, and MongoDB. For more information, see the
|
|
[Quarkus Dev Services guide](https://quarkus.io/guides/dev-services).
|
|
|
|
## Write tests for the API endpoints
|
|
|
|
Test the `GET /api/customers` and `POST /api/customers` endpoints using REST
|
|
Assured. The `io.rest-assured:rest-assured` library was already added as a test
|
|
dependency when you generated the project.
|
|
|
|
Create `CustomerResourceTest.java` and annotate it with `@QuarkusTest`. This
|
|
bootstraps the application along with the required services using Dev Services.
|
|
Because you haven't configured datasource properties, Dev Services automatically
|
|
starts a PostgreSQL database using Testcontainers.
|
|
|
|
```java
|
|
package com.testcontainers.demo;
|
|
|
|
import static io.restassured.RestAssured.given;
|
|
import static org.hamcrest.CoreMatchers.is;
|
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
|
|
import io.quarkus.test.junit.QuarkusTest;
|
|
import io.restassured.common.mapper.TypeRef;
|
|
import io.restassured.http.ContentType;
|
|
import java.util.List;
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
@QuarkusTest
|
|
class CustomerResourceTest {
|
|
|
|
@Test
|
|
void shouldGetAllCustomers() {
|
|
List<Customer> customers = given().when()
|
|
.get("/api/customers")
|
|
.then()
|
|
.statusCode(200)
|
|
.extract()
|
|
.as(new TypeRef<>() {});
|
|
assertFalse(customers.isEmpty());
|
|
}
|
|
|
|
@Test
|
|
void shouldCreateCustomerSuccessfully() {
|
|
Customer customer = new Customer(null, "John", "john@gmail.com");
|
|
given().contentType(ContentType.JSON)
|
|
.body(customer)
|
|
.when()
|
|
.post("/api/customers")
|
|
.then()
|
|
.statusCode(201)
|
|
.body("name", is("John"))
|
|
.body("email", is("john@gmail.com"));
|
|
}
|
|
}
|
|
```
|
|
|
|
Here's what the test does:
|
|
|
|
- `@QuarkusTest` starts the full Quarkus application with Dev Services enabled.
|
|
- Dev Services starts a PostgreSQL container using Testcontainers and configures
|
|
the datasource automatically.
|
|
- `shouldGetAllCustomers()` calls `GET /api/customers` and verifies that seeded
|
|
data from the Flyway migration is returned.
|
|
- `shouldCreateCustomerSuccessfully()` sends a `POST /api/customers` request and
|
|
verifies the response contains the created customer data.
|
|
|
|
## Customize test configuration
|
|
|
|
By default, the Quarkus test instance starts on port 8081 and uses a
|
|
`postgres:14` Docker image. Customize both by adding these properties to
|
|
`src/main/resources/application.properties`:
|
|
|
|
```properties
|
|
quarkus.http.test-port=0
|
|
quarkus.datasource.devservices.image-name=postgres:15.2-alpine
|
|
```
|
|
|
|
Setting `quarkus.http.test-port=0` starts the application on a random available
|
|
port, avoiding port conflicts. The `devservices.image-name` property lets you
|
|
pin the PostgreSQL image to a specific version that matches production.
|
|
|
|
## Test with services not supported by Dev Services
|
|
|
|
Your application might use a service that Dev Services doesn't support out of
|
|
the box. In that case, use `QuarkusTestResourceLifecycleManager` to start the
|
|
service before the Quarkus application starts for testing.
|
|
|
|
For example, suppose the application uses CockroachDB. First, add the
|
|
CockroachDB Testcontainers module dependency:
|
|
|
|
```xml
|
|
<dependency>
|
|
<groupId>org.testcontainers</groupId>
|
|
<artifactId>cockroachdb</artifactId>
|
|
<scope>test</scope>
|
|
</dependency>
|
|
```
|
|
|
|
Create a `CockroachDBTestResource` that implements
|
|
`QuarkusTestResourceLifecycleManager`:
|
|
|
|
```java
|
|
package com.testcontainers.demo;
|
|
|
|
import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import org.testcontainers.containers.CockroachContainer;
|
|
|
|
public class CockroachDBTestResource implements QuarkusTestResourceLifecycleManager {
|
|
|
|
CockroachContainer cockroachdb;
|
|
|
|
@Override
|
|
public Map<String, String> start() {
|
|
cockroachdb = new CockroachContainer("cockroachdb/cockroach:v22.2.0");
|
|
cockroachdb.start();
|
|
Map<String, String> conf = new HashMap<>();
|
|
conf.put("quarkus.datasource.jdbc.url", cockroachdb.getJdbcUrl());
|
|
conf.put("quarkus.datasource.username", cockroachdb.getUsername());
|
|
conf.put("quarkus.datasource.password", cockroachdb.getPassword());
|
|
return conf;
|
|
}
|
|
|
|
@Override
|
|
public void stop() {
|
|
cockroachdb.stop();
|
|
}
|
|
}
|
|
```
|
|
|
|
Use the `CockroachDBTestResource` with `@QuarkusTestResource` in a test class:
|
|
|
|
```java
|
|
package com.testcontainers.demo;
|
|
|
|
import static io.restassured.RestAssured.given;
|
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
|
|
import io.quarkus.test.common.QuarkusTestResource;
|
|
import io.quarkus.test.junit.QuarkusTest;
|
|
import io.restassured.common.mapper.TypeRef;
|
|
import java.util.List;
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
@QuarkusTest
|
|
@QuarkusTestResource(value = CockroachDBTestResource.class, restrictToAnnotatedClass = true)
|
|
class CockroachDBTest {
|
|
|
|
@Test
|
|
void shouldGetAllCustomers() {
|
|
List<Customer> customers = given().when()
|
|
.get("/api/customers")
|
|
.then()
|
|
.statusCode(200)
|
|
.extract()
|
|
.as(new TypeRef<>() {});
|
|
assertFalse(customers.isEmpty());
|
|
}
|
|
}
|
|
```
|
|
|
|
The `restrictToAnnotatedClass = true` attribute ensures the CockroachDB
|
|
container only starts when running this specific test class, rather than being
|
|
activated for all tests.
|