Reputation: 693
I am using a singleton test-container for running multiple integration tests like this :
@SpringBootTest(webEnvironment = RANDOM_PORT)
public abstract class BaseIT {
static final PostgreSQLContainer<?> postgreSQLContainer;
static {
postgreSQLContainer =
new PostgreSQLContainer<>(DockerImageName.parse("postgres:13"))
.withDatabaseName("test")
.withUsername("duke")
.withPassword("s3cret")
.withReuse(true);
postgreSQLContainer.start();
}
@DynamicPropertySource
static void datasourceConfig(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl);
registry.add("spring.datasource.password", postgreSQLContainer::getPassword);
registry.add("spring.datasource.username", postgreSQLContainer::getUsername);
}
}
And then extending from the test the base it
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class SecondApplicationIT extends BaseIT{
@Autowired
private TestRestTemplate testRestTemplate;
@Autowired
private TodoRepository todoRepository;
@AfterEach
public void cleanup() {
this.todoRepository.deleteAll();
}
@Test
void contextLoads() {
this.todoRepository.saveAll(List.of(new Todo("Write blog post", LocalDateTime.now().plusDays(2)),
new Todo("Clean appartment", LocalDateTime.now().plusDays(4))));
ResponseEntity<ArrayNode> result = this.testRestTemplate.getForEntity("/todos", ArrayNode.class);
assertEquals(200, result.getStatusCodeValue());
assertTrue(result.getBody().isArray());
assertEquals(2, result.getBody().size());
}
}
but now the container is running even after the SecondApplicationIT
is finished, how can i stop the container after finishing all test classes
which is extending the BaseIt
P.S:
i tried with @AfterEach
and stopping the container there but it did not work
Upvotes: 6
Views: 7967
Reputation: 1572
This can be achieved by following the Singleton Container Pattern without using withReuse(true)
. No need to call stop()
also, since in this case, the container lifetime will be bound to the lifetime of the JVM process (through means of the Ryuk resource reaper mechanism).
Upvotes: 3
Reputation: 693
Solved it by my own, the .withReuse(true); is not needed there in order to allow the ryuk container to start. the ryuk container will then remove all running containers which is ran by the IT.
see: https://engineering.zalando.com/posts/2021/02/integration-tests-with-testcontainers.html
Upvotes: 2
Reputation: 3790
You can use JUnit extension Testcontainers provides.
Mark the class with @Testcontainers
, and the container fields with @Container
.
Containers in instance fields will be initialized and stopped for every test case. Static fields will be started once for a class and stopped after.
So something like:
@SpringBootTest(webEnvironment = RANDOM_PORT)
@Testcontainers
public abstract class BaseIT {
@Container
static final PostgreSQLContainer<?> postgreSQLContainer =
new PostgreSQLContainer<>(DockerImageName.parse("postgres:13"))
.withDatabaseName("test")
.withUsername("duke")
.withPassword("s3cret");
@DynamicPropertySource
static void datasourceConfig(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl);
registry.add("spring.datasource.password", postgreSQLContainer::getPassword);
registry.add("spring.datasource.username", postgreSQLContainer::getUsername);
}
}
Note that you're also specifying withReuse(true)
, which can make the container to not be registered for automatic lifecycle management (if the environment you're running tests opts in for that with testcontainers.reuse.enabled = true
in ~/.testcontainers.properties
)
Upvotes: 0