Search code examples
postgresqlspring-bootdockerwindows-10integration-testing

Cannot run DB Integration tests with Spring Boot and Testcontainers


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

Solution

  • 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();
        }