I try to run DB Integration tests with Spring Boot and Testcontainers but without success
I added testcontainer to my pom.xml
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>1.10.6</version>
<scope>test</scope>
</dependency>
Here is the extract of application.properties under test/resources folder
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=create-drop
.......
logging.file.name=staffaccess-log.log
spring.jpa.properties.hibernate.default_schema=staffaccess
spring.jpa.show-sql=true
debug=true
logging.level.org.springframework.web=ERROR
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL94Dialect
........
Here is the class where I create a container definition
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(initializers = {UserRepositoryTCIntegrationTest.Initializer.class})
public class UserRepositoryTCIntegrationTest extends UserRepositoryCommonIntegrationTests {
@ClassRule
public static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer("postgres:11.1")
.withDatabaseName("integration-tests-db")
.withUsername("sa")
.withPassword("sa");
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());
}
}
}
But when I run an integration test, I have the following error
java.lang.ExceptionInInitializerError
at sun.misc.Unsafe.ensureClassInitialized(Native Method)
at sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(UnsafeFieldAccessorFactory.java:43)
at sun.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:156)
at java.lang.reflect.Field.acquireFieldAccessor(Field.java:1088)
at java.lang.reflect.Field.getFieldAccessor(Field.java:1069)
at java.lang.reflect.Field.get(Field.java:393)
at org.junit.runners.model.FrameworkField.get(FrameworkField.java:92)
at org.junit.runners.model.TestClass.collectAnnotatedFieldValues(TestClass.java:249)
at org.junit.runners.ParentRunner.classRules(ParentRunner.java:280)
at org.junit.runners.ParentRunner.withClassRules(ParentRunner.java:268)
at org.junit.runners.ParentRunner.classBlock(ParentRunner.java:217)
at org.junit.runners.ParentRunner.run(ParentRunner.java:412)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:221)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: com.github.dockerjava.api.exception.NotFoundException: {"message":"Get https://quay.io/v1/_ping: dial tcp: lookup quay.io on 192.168.65.1:53: no such host"}
It seems that there is a problem with docker
I installed docker for windows (I am under windows 10)
as we seem to need a postgres image as the following code suggests
@ClassRule
public static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer("postgres:11.1")
I tried to pull the postgres image, but it gives me an error
C:\Users\xflamant>docker pull postgres
Using default tag: latest
Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp 34.228.211.243:443: getsockopt: connection refused
here is my host file (C:\Windows\System32\drivers\etc\hosts)
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
# 102.54.94.97 rhino.acme.com # source server
# 38.25.63.10 x.acme.com # x client host
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
# Added by Docker Desktop
10.124.76.38 host.docker.internal
10.124.76.38 gateway.docker.internal
#added to pull postgres image
34.228.211.243 registry-1.docker.io
# To allow the same kube context to work on the host and the container:
127.0.0.1 kubernetes.docker.internal
# End of section
I found the solution, in fact I pulled another docker image of Postgres: postgres:13.4-buster. The discussion is closed
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
"spring.datasource.url=jdbc:tc:postgresql:13.4-buster:///databasename?TC_INITSCRIPT=file:src/test/resources/init_script.sql",
"spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver"
})
@AutoConfigureMockMvc
@Testcontainers
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class ApplicationControllerTest extends InserDataForIntegrationTests {
@Autowired
private MockMvc mockMvc;
@Autowired
private AuthenticationManager authManager;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private WebApplicationContext context;
@Container
@Shared
public static PostgreSQLContainer postgreSQLContainer = (PostgreSQLContainer) new PostgreSQLContainer("postgres:13.4-buster")
.withDatabaseName("databasename")
.withUsername("sa")
.withPassword("sa");;
@DynamicPropertySource
static void postgresqlProperties(DynamicPropertyRegistry registry) throws URISyntaxException {
registry.add("spring.datasource.driver-class-name", () -> "org.testcontainers.jdbc.ContainerDatabaseDriver");
registry.add("spring.datasource.url", () -> "jdbc:tc:postgresql:13.4-buster:///databasename?TC_INITSCRIPT=file:src/test/resources/init_script.sql");
registry.add("spring.datasource.username", postgreSQLContainer::getUsername);
registry.add("spring.datasource.password", postgreSQLContainer::getPassword);
}
@BeforeAll
@Transactional
public void setup() {
postgreSQLContainer.start();
mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken("username", "password");
Authentication auth = authManager.authenticate(authReq);
SecurityContextHolder.getContext().setAuthentication(auth);
insertData();
}