javaspringtestingspring-data-jpatestcontainers

Spring @DataJpaTest with @TestContainers in JUnit 5


This is an extension to Spring @DataJpaTest with JUnit 5 the main difference is the addition of test containers.

I tried to keep things at minimum in a git-repo sample.

The test is pretty straight forward

@DataJpaTest
@Testcontainers
@ContextConfiguration(classes = {
        DemoApplicationTests.Config.class
})
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class DemoApplicationTests {

    @Autowired
    private Artifacts artifacts;

    @Test
    void contextLoads() {
        assertThat(artifacts).isNotNull();
    }

    @Container
    private static final MySQLContainer<?> MYSQL = new MySQLContainer<>("mysql:5.7");

    @Configuration
    static class Config {
        @Bean
        public DataSource dataSource() {

            final DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setUrl(MYSQL.getJdbcUrl());
            dataSource.setUsername(MYSQL.getUsername());
            dataSource.setPassword(MYSQL.getPassword());

            await().pollInterval(Duration.ofSeconds(2L))
                    .atMost(Duration.ofMinutes(2L))
                    .until(() -> {
                        try (final Connection c = dataSource.getConnection()) {
                            c.prepareStatement("select 1 from dual");
                            return true;
                        } catch (SQLException e) {
                            return false;
                        }
                    });

            return dataSource;

        }

    }

}

The main application I kept to a minimum as well

@SpringBootApplication
@EnableTransactionManagement
@EnableJpaRepositories
@EntityScan
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

But running the test I get the following stack trace segment:


Caused by: java.lang.IllegalStateException: Unable to retrieve @EnableAutoConfiguration base packages
    at org.springframework.boot.autoconfigure.AutoConfigurationPackages.get(AutoConfigurationPackages.java:78)
    at org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport.getBasePackages(AbstractRepositoryConfigurationSourceSupport.java:79)
    at org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport$AutoConfiguredAnnotationRepositoryConfigurationSource.getBasePackages(AbstractRepositoryConfigurationSourceSupport.java:138)
    at org.springframework.data.repository.config.RepositoryConfigurationSourceSupport.lambda$getCandidates$2(RepositoryConfigurationSourceSupport.java:82)

Solution

  • I found two ways of getting this working. One approach is

    @ContextConfiguration(classes = {
      DemoApplication.class,
      DemoApplicationTests.Config.class
    })
    

    Which loads up the configuration from DemoApplication. Though it is generally cleaner, if you have other services like EnableRedisRepositories and EnableKafka the test may still fail as those resources may not be configured in your script.

    Alternatively the Config class can be enabled so only JPA testing is performed. This is what I eventually opted with as I had EnableRedisRepositories on the code I extracted the sample from.

        @Configuration
        @EnableTransactionManagement
        @EnableJpaRepositories
        @EntityScan
        static class Config