1

I tested my Spring Boot app using local PGSQL DB. Now I want to modify tests to use PGSQL running in Testcontainers.

I modified my test configuration class to use Testcontainers and to expose data source connecting to the port returned by Testcontainers:

@TestConfiguration
@SpringBootApplication(exclude = { HazelcastAutoConfiguration.class })
@ComponentScan(basePackages = { "rw.gov.dgie.tm" })
@EntityScan("rw.gov.dgie.tm")
@EnableJpaRepositories(basePackages = { "rw.gov.dgie.tm" })
@EnableAsync(proxyTargetClass = true)
@EnableTransactionManagement
@Testcontainers
public class DbTestConfig {
@Autowired
private DataSource dataSource;

@SuppressWarnings("resource")
@Container
    public static ComposeContainer dockerComposeContainer =
        new ComposeContainer(new File("../docker/catalog-test.yml"))
                .withExposedService("db-catalog", 5432)
                .withRemoveVolumes(false)
                .withLocalCompose(true)
                .waitingFor("db-catalog", new DockerHealthcheckWaitStrategy());

@Bean
    public DataSource dataSource(){
    DriverManagerDataSource source = new DriverManagerDataSource();
    String url = "jdbc:postgresql://" + dockerComposeContainer.getServiceHost("db-catalog", 5432) + ":" + dockerComposeContainer.getServicePort("db-catalog", 5432) + "/db-catalog";
    source.setDriverClassName("org.postgresql.Driver");
    source.setUrl(url);
    source.setUsername("sa");
    source.setPassword("sa");
    return source;
}

}

I am using the following application-test.yml file:

  datasource:
      type: com.zaxxer.hikari.HikariDataSource
      driver-class-name: org.postgresql.Driver
      url: jdbc:postgresql://localhost:5432/db_catalog
      username: db_catalog
      password: qwerty
      hikari:
        poolName: Hikari
        auto-commit: false
    jpa:
      show-sql: true
      generate-ddl: true
      properties:
        hibernate:
          dialect: org.hibernate.dialect.PostgreSQLDialect
          ddl-auto: update
          generate_statistics: false

However, when running test which was run OK with local DB I get the following exception:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Failed to initialize dependency 'dataSourceScriptDatabaseInitializer' of LoadTimeWeaverAware bean 'entityManagerFactory': Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Unsatisfied dependency expressed through method 'dataSourceScriptDatabaseInitializer' parameter 0: Error creating bean with name 'dbTestConfig': Unsatisfied dependency expressed through field 'dataSource': Error creating bean with name 'dataSource': Requested bean is currently in creation: Is there an unresolvable circular reference?

How can I manage that?

1 Answer 1

0

Few things:

  • TestContainers should be used only for testing, hence move them to the test class folders.
  • Remove @Autowired private DataSource dataSource from
    DbTestConfig. The class is responsible for creating the datasource bean and before creating the bean, the program tries to autowire it. Hence, the error:

Error creating bean with name 'dbTestConfig': Unsatisfied dependency expressed through field 'dataSource': Error creating bean with name 'dataSource': Requested bean is currently in creation:

  • As an alternative, you should use PostgreSQLContainer

Here are the maven dependency

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>postgresql</artifactId>
    <version>1.19.8</version>
    <scope>test</scope>
</dependency>

Code for instantiating the postgres container:

PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer("postgres:14.1");
    postgreSQLContainer.withDatabaseName("postgres")
        .withUsername("postgres")
        .withPassword("postgres");
    postgreSQLContainer.start();

The constructor takes the docker image name. As a prerequisite you must have docker desktop installed on windows.

  • Later you can create your datasource bean where you can retrieve the database properties from the postgreSQLContainer object:

     public DataSource datasource() {
    
     DriverManagerDataSource dataSource = new DriverManagerDataSource();
     dataSource.setDriverClassName(postgreSQLContainer.getDriverClassName());
     dataSource.setUrl(postgreSQLContainer.getJdbcUrl());
     dataSource.setUsername(postgreSQLContainer.getUsername());
     dataSource.setPassword(postgreSQLContainer.getPassword());
     return dataSource;
    

}

please refer to a sample test configuration

For more details refer

Sign up to request clarification or add additional context in comments.

1 Comment

Did my answer help or you are looking for more details. Would be glad to provide more inputs on this :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.