mirror of
https://github.com/github/awesome-copilot.git
synced 2026-03-20 08:05:12 +00:00
- Introduced MockMvcTester for AssertJ-style assertions in Spring MVC testing. - Added @RestClientTest for testing REST clients with MockRestServiceServer. - Implemented RestTestClient as a modern alternative to TestRestTemplate. - Documented migration steps from Spring Boot 3.x to 4.0, including dependency and annotation changes. - Created an overview of test slices to guide testing strategies. - Included Testcontainers setup for JDBC testing with PostgreSQL and MySQL. - Enhanced @WebMvcTest documentation with examples for various HTTP methods and validation.
5.3 KiB
5.3 KiB
Testcontainers JDBC
Testing JPA repositories with real databases using Testcontainers.
Overview
Testcontainers provides real database instances in Docker containers for integration testing. More reliable than H2 for production parity.
PostgreSQL Setup
Dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-postgresql</artifactId>
<scope>test</scope>
</dependency>
Basic Test
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Testcontainers
class OrderRepositoryPostgresTest {
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:18");
@Autowired
private OrderRepository orderRepository;
@Autowired
private TestEntityManager entityManager;
}
MySQL Setup
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-mysql</artifactId>
<scope>test</scope>
</dependency>
@Container
@ServiceConnection
static MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.4");
Multiple Databases
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Testcontainers
class MultiDatabaseTest {
@Container
@ServiceConnection(name = "primary")
static PostgreSQLContainer<?> primaryDb = new PostgreSQLContainer<>("postgres:18");
@Container
@ServiceConnection(name = "analytics")
static PostgreSQLContainer<?> analyticsDb = new PostgreSQLContainer<>("postgres:18");
}
Container Reuse (Speed Optimization)
Add to ~/.testcontainers.properties:
testcontainers.reuse.enable=true
Then enable reuse in code:
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:18")
.withReuse(true);
Database Initialization
With SQL Scripts
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:18")
.withInitScript("schema.sql");
With Flyway
@SpringBootTest
@Testcontainers
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class MigrationTest {
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:18");
@Autowired
private Flyway flyway;
@Test
void shouldApplyMigrations() {
flyway.migrate();
// Test code
}
}
Advanced Configuration
Custom Database/Schema
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:18")
.withDatabaseName("testdb")
.withUsername("testuser")
.withPassword("testpass")
.withInitScript("init-schema.sql");
Wait Strategies
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:18")
.waitingFor(Wait.forLogMessage(".*database system is ready.*", 1));
Test Example
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Testcontainers
class OrderRepositoryTest {
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:18");
@Autowired
private OrderRepository orderRepository;
@Autowired
private TestEntityManager entityManager;
@Test
void shouldFindOrdersByStatus() {
// Given
entityManager.persist(new Order("PENDING"));
entityManager.persist(new Order("COMPLETED"));
entityManager.flush();
// When
List<Order> pending = orderRepository.findByStatus("PENDING");
// Then
assertThat(pending).hasSize(1);
assertThat(pending.get(0).getStatus()).isEqualTo("PENDING");
}
@Test
void shouldSupportPostgresSpecificFeatures() {
// Can use Postgres-specific features like:
// - JSONB columns
// - Array types
// - Full-text search
}
}
@DynamicPropertySource Alternative
If not using @ServiceConnection:
@SpringBootTest
@Testcontainers
class OrderServiceTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:18");
@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);
}
}
Supported Databases
| Database | Container Class | Maven Artifact |
|---|---|---|
| PostgreSQL | PostgreSQLContainer | testcontainers-postgresql |
| MySQL | MySQLContainer | testcontainers-mysql |
| MariaDB | MariaDBContainer | testcontainers-mariadb |
| SQL Server | MSSQLServerContainer | testcontainers-mssqlserver |
| Oracle | OracleContainer | testcontainers-oracle-free |
| MongoDB | MongoDBContainer | testcontainers-mongodb |
Best Practices
- Use @ServiceConnection when possible (Spring Boot 3.1+)
- Enable container reuse for faster local builds
- Use specific versions (postgres:18) not latest
- Keep container config in static field
- Use @DataJpaTest with AutoConfigureTestDatabase.Replace.NONE