I am using 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 runing 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
CodePudding user response:
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
)
CodePudding user response:
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