Appearance
Fresh
Write tests
Back
Testing a Spring Boot REST API with Testcontainers
Learn how to create a Spring Boot REST API with Spring Data JPA and PostgreSQL, then test it using Testcontainers and REST Assured.
Java Testing with Docker
25 minutes
Write tests with Testcontainers
Copy as Markdown
Open MarkdownAsk Docs AIClaudeOpen in Claude
Table of contents
To test the REST API, you need a running Postgres database and a started Spring context. Testcontainers spins up Postgres in a Docker container and @DynamicPropertySource connects it to Spring.
Write the test
Create CustomerControllerTest.java:
java
package com.testcontainers.demo;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.hasSize;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import java.util.List;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.postgresql.PostgreSQLContainer;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class CustomerControllerTest {
@LocalServerPort
private Integer port;
static PostgreSQLContainer postgres = new PostgreSQLContainer(
"postgres:16-alpine"
);
@BeforeAll
static void beforeAll() {
postgres.start();
}
@AfterAll
static void afterAll() {
postgres.stop();
}
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Autowired
CustomerRepository customerRepository;
@BeforeEach
void setUp() {
RestAssured.baseURI = "http://localhost:" + port;
customerRepository.deleteAll();
}
@Test
void shouldGetAllCustomers() {
List<Customer> customers = List.of(
new Customer(null, "John", "john@mail.com"),
new Customer(null, "Dennis", "dennis@mail.com")
);
customerRepository.saveAll(customers);
given()
.contentType(ContentType.JSON)
.when()
.get("/api/customers")
.then()
.statusCode(200)
.body(".", hasSize(2));
}
}Here's what the test does:
@SpringBootTeststarts the full application on a random port.- A
PostgreSQLContainerstarts in@BeforeAlland stops in@AfterAll. @DynamicPropertySourceregisters the container's JDBC URL, username, and password with Spring so that the datasource connects to the test container.@BeforeEachdeletes all customer rows before each test to prevent test pollution.shouldGetAllCustomers()inserts two customers, callsGET /api/customers, and verifies the response contains 2 records.