📖 Scenario: You are building a Spring Boot application that needs to test database operations reliably. Instead of using a real database server, you want to use a test container that runs a temporary database during tests. This helps keep tests isolated and easy to run anywhere.
🎯 Goal: Create a Spring Boot test class that uses Testcontainers to start a PostgreSQL database container. Configure the test to connect to this container and verify a simple database connection.
📋 What You'll Learn
Create a PostgreSQLContainer instance with the image postgres:15-alpine
Configure the container to start before tests
Set Spring datasource properties dynamically from the container
Write a simple test method that checks the datasource URL contains jdbc:postgresql
💡 Why This Matters
🌍 Real World
Testcontainers allow developers to run real database instances in containers during automated tests. This ensures tests run consistently on any machine without manual database setup.
💼 Career
Many companies use Testcontainers for integration testing in Java Spring Boot projects. Knowing how to set up and use Testcontainers is valuable for backend developers and QA engineers.
Progress0 / 4 steps
1
Set up PostgreSQLContainer instance
Create a static variable called postgresContainer of type PostgreSQLContainer using the image "postgres:15-alpine". Initialize it with new PostgreSQLContainer<>("postgres:15-alpine").
Spring Boot
Hint
Use static PostgreSQLContainer<?> postgresContainer = new PostgreSQLContainer<>("postgres:15-alpine") to create the container.
2
Start container before tests
Add a static block to start postgresContainer before any tests run by calling postgresContainer.start() inside the block.
Spring Boot
Hint
Use a static block static { postgresContainer.start(); } to start the container once.
3
Configure Spring datasource properties dynamically
Create a method annotated with @DynamicPropertySource named registerPgProperties that takes a DynamicPropertyRegistry parameter called registry. Inside, set the properties spring.datasource.url, spring.datasource.username, and spring.datasource.password using registry.add with lambdas returning postgresContainer.getJdbcUrl(), postgresContainer.getUsername(), and postgresContainer.getPassword() respectively.
Spring Boot
Hint
Use @DynamicPropertySource and registry.add with method references to set the datasource properties.
4
Write a test method to verify datasource URL
Add a test method annotated with @Test named testDatasourceUrl. Inject a javax.sql.DataSource parameter named dataSource. Inside, get the connection URL from dataSource.getConnection().getMetaData().getURL() and assert it contains the string "jdbc:postgresql" using org.junit.jupiter.api.Assertions.assertTrue.
Spring Boot
Hint
Write a @Test method that gets the connection URL from the injected DataSource and asserts it contains "jdbc:postgresql".
Practice
(1/5)
1. What is the main purpose of using Testcontainers in Spring Boot database testing?
easy
A. To run real database instances in temporary containers for reliable tests
B. To mock database calls without any real database
C. To speed up unit tests by skipping database interactions
D. To deploy databases permanently on production servers
Solution
Step 1: Understand Testcontainers role
Testcontainers run real database instances inside temporary containers during tests.
Step 2: Compare with other options
Mocking or skipping databases is not what Testcontainers do; they provide real environments temporarily.
Final Answer:
To run real database instances in temporary containers for reliable tests -> Option A
Quick Check:
Testcontainers purpose = run real temporary databases [OK]
Hint: Testcontainers run real temporary databases, not mocks [OK]
2. Which of the following is the correct way to start a PostgreSQL Testcontainer in a Spring Boot test class?
easy
A. static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:latest").start();
B. PostgreSQLContainer postgres = new PostgreSQLContainer("postgres:latest").run();
C. static PostgreSQLContainer postgres = new PostgreSQLContainer("postgres:latest").begin();
D. PostgreSQLContainer postgres = new PostgreSQLContainer().start();
Solution
Step 1: Check correct instantiation and start method
The correct way is to create a static container with generic type and call start().
Step 2: Validate options
static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:latest").start(); uses correct syntax with generic type and start(). Others use wrong method names or miss generics.
Final Answer:
static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:latest").start(); -> Option A
Quick Check:
Use start() with generic type for Testcontainers [OK]
Hint: Use start() method and generic type for containers [OK]
Common Mistakes:
Using .run() or .begin() instead of .start()
Omitting generic type
Not declaring container as static when needed
3. Given this Spring Boot test snippet using Testcontainers:
@Testcontainers
class MyRepositoryTest {
@Container
static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:13").withDatabaseName("testdb").withUsername("user").withPassword("pass");
@Autowired
MyRepository repo;
@Test
void testCount() {
long count = repo.count();
System.out.println(count);
}
}
What will System.out.println(count); print if the database is empty?
medium
A. null
B. 0
C. Throws NullPointerException
D. 1
Solution
Step 1: Understand repo.count() behavior
The count() method returns the number of records in the repository's table.
Step 2: Database is empty so count is zero
Since the database is fresh and empty, count() returns 0, not null or exception.
Final Answer:
0 -> Option B
Quick Check:
Empty DB count() = 0 [OK]
Hint: Empty database count returns zero, not null or error [OK]
Common Mistakes:
Expecting null instead of zero
Assuming count() throws exception on empty DB
Confusing count() with find methods
4. You wrote this test using Testcontainers but it fails with org.testcontainers.containers.ContainerLaunchException. What is the likely cause?
@Container
static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:latest");
@Test
void testDb() {
// test code
}
medium
A. The PostgreSQL image name is incorrect
B. The container must be started manually with .start() in the test
C. Docker is not running or accessible on the test machine
D. Testcontainers do not support PostgreSQL
Solution
Step 1: Understand ContainerLaunchException meaning
This exception usually means Docker cannot start the container.
Step 2: Check common causes
Most common cause is Docker daemon not running or inaccessible to Testcontainers.
Final Answer:
Docker is not running or accessible on the test machine -> Option C
Quick Check:
ContainerLaunchException = Docker not running [OK]
Hint: Check Docker daemon is running if container launch fails [OK]
Common Mistakes:
Thinking image name is wrong when it is correct
Trying to start container manually when @Container does it
Believing Testcontainers don't support PostgreSQL
5. You want to write a Spring Boot integration test using Testcontainers with a MySQL database. You want the container to start once before all tests and stop after all tests. Which setup is correct?
hard
A. Use @SpringBootTest without any container setup; rely on embedded database
B. Create a new MySQLContainer instance inside each test method and call start() manually
C. Use @BeforeEach to start a MySQLContainer and @AfterEach to stop it
D. Declare a static MySQLContainer with @Container annotation in the test class and use @Testcontainers on the class
Solution
Step 1: Understand lifecycle annotations
Using static container with @Container and @Testcontainers on class starts container once before all tests and stops after all.
Step 2: Compare other options
Creating container per test or starting/stopping each test is inefficient. Embedded DB is different approach.
Final Answer:
Declare a static MySQLContainer with @Container annotation in the test class and use @Testcontainers on the class -> Option D
Quick Check:
Static @Container + @Testcontainers = start once before all tests [OK]
Hint: Use static @Container field with @Testcontainers class annotation [OK]
Common Mistakes:
Starting container inside each test method
Using @BeforeEach/@AfterEach for container lifecycle
Assuming embedded DB replaces Testcontainers
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.