Reputation: 4640
My App under test with spring (core) wants to connect to a database by testcontainer, but the testcontainer is not started at this point. How can I achieve that the testcontainer gets ready and then the whole context ist started up?
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@Testcontainers
@SpringJUnitWebConfig(locations = {"classpath:it-context.xml"})
public class IntegrationTest {
@Container
private PostgreSQLContainer postgresqlContainer = new PostgreSQLContainer();
@Autowired
private StatusBean status;
@Test
public void appStartedSuccessful(){
// app & database successful started and connected
System.out.println(postgresqlContainer.getJdbcUrl());
System.out.println(postgresqlContainer.getTestQueryString());
System.out.println(status.getStartupTimestamp());
}
}
Upvotes: 1
Views: 1834
Reputation: 336
In SpringBoot you will have to overwrite the DB parameter using the ones from Postgres-Testcontainer by ApplicationContextInitializer. Testcontainers lifecycle management will handle the rest. Should look somehow like this:
@Testcontainers
@SpringJUnitWebConfig(locations = {"classpath:it-context.xml"})
@ContextConfiguration(initializers = {IntegrationTest.Initializer.class})
public class IntegrationTest {
@Container
private static PostgreSQLContainer postgresqlContainer = new PostgreSQLContainer();
static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
TestPropertyValues.of(
"spring.datasource.url=" + postgresqlContainer.getJdbcUrl(),
"spring.datasource.username=" + postgresqlContainer.getUsername(),
"spring.datasource.password=" + postgresqlContainer.getPassword()
).applyTo(configurableApplicationContext.getEnvironment());
}
}
@Autowired
private StatusBean status;
@Test
public void appStartedSuccessful(){
// app & database successful started and connected
System.out.println(postgresqlContainer.getJdbcUrl());
System.out.println(postgresqlContainer.getTestQueryString());
System.out.println(status.getStartupTimestamp());
}
}
Upvotes: 0
Reputation: 41
You can write your Datasource Bean class integration tests and create a datasrouce from the parameters from the postgresqlContainer
@Configuration
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Testcontainers
public class TestConfiguration{
PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>(POSTGRES_TEST_IMAGE)
.withInitScript("somepath/init_postgresql.sql")
@Primary
@Bean
public DataSource dataSource(){
HikariConfig hikariConfig=new HikariConfig();
hikariConfig.setJdbcUrl(postgres.getUrl());
hikariConfig.setUsername(postgres.getUsername());
hikariConfig.setPassword(postgres.getPassword());
hikariConfig.setDriverClassName(postgres.getDriverClassName());
HikariDataSource hikariDataSource=new HikariDataSource(hikariConfig);
return hikariDataSource;
}
}
And import the above configuration class into your springboot test, it will automatically override the datasource with TestContainer's Postgres datasoruce.
Your test should look like this
@ExtendWith({SpringExtension.clas})
@SpringBootTest(classes = {DataSourceConfiguration.class, TestConfiguration.class})
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@Testcontainers
public class RepoTest {
@Autowired
TestRepository testRepository;
@Test
public void testRepo() {
System.out.println("*****************" + testRepository.existsById(1L));
}
}
For details refer this link : https://medium.com/@arpitsharma14/testcontainer-springboot-tests-faa05b71a7dc
Upvotes: 0
Reputation: 11818
You probably want to wait for the containers to start and be ready
See the documentation though the code seems to indicate that the container should be waiting for a magic log entry, perhaps that's not working for you for some reason.
If you Thread.sleep
in your test method, does the Pg container finally arrive as expected? Anything in the container logs to indicate a failure of some sort (unlikely, given the static
trick worked for you).
I don't see anything in the JUnit5 integration docs to indicate any manual waiting required when using @Container
.
Upvotes: 0