Careeroza
@SpringBootTest and Testcontainers
Full Integration Test
@SpringBootTest starts the whole application. With RANDOM_PORT it even starts Tomcat, and you call it over real HTTP:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
class ProductApiIT {
@Autowired TestRestTemplate rest;
@Test
void createThenFetch() {
var req = new CreateProductRequest("ELE-2001", "Laptop Stand", "Aluminium",
new BigDecimal("1499.00"), 40, "Electronics");
ResponseEntity<ProductResponse> created = rest.postForEntity("/api/products", req, ProductResponse.class);
assertThat(created.getStatusCode()).isEqualTo(HttpStatus.CREATED);
ProductResponse fetched = rest.getForObject(created.getHeaders().getLocation(), ProductResponse.class);
assertThat(fetched.name()).isEqualTo("Laptop Stand");
}
}Testcontainers: a Real Database in Tests
H2 behaves differently from MySQL/PostgreSQL in small ways. Testcontainers starts a real database in Docker for the test run. Since Boot 3.1, @ServiceConnection wires its URL, user and password into Spring automatically.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Testcontainers
class ProductApiPostgresIT {
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine");
@Autowired TestRestTemplate rest;
@Test
void listWorksOnRealPostgres() {
ResponseEntity<String> res = rest.getForEntity("/api/products", String.class);
assertThat(res.getStatusCode().is2xxSuccessful()).isTrue();
}
}Example
./mvnw verifyExample output
INFO tc.postgres:16-alpine : Creating container for image: postgres:16-alpine INFO tc.postgres:16-alpine : Container postgres:16-alpine started in PT2.1S INFO c.s.ProductApiPostgresIT : Started ProductApiPostgresIT in 5.733 seconds [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] BUILD SUCCESS
Note: Testcontainers needs Docker running on the machine (or CI runner). GitHub Actions Ubuntu runners have Docker installed.