Search code examples
javaspring-bootmockitointegration-testingjunit5

Spring test: configure datasource for org.springframework.test.context.jdbc.Sql


In my Spring Boot project I have two datasources:

    @Primary
    @Bean(name = "pgDatasource")
    public BasicDataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(env.getProperty("spring.datasource.dbcp2.driver-class-name"));
        dataSource.setUrl(env.getProperty("spring.datasource.dbcp2.url"));
        dataSource.setUsername(env.getProperty("spring.datasource.dbcp2.username"));
        dataSource.setPassword(env.getProperty("spring.datasource.dbcp2.password"));
        dataSource.setMaxActive(Integer.valueOf(env.getProperty("spring.datasource.dbcp2.max-total")));
        dataSource.setMaxIdle(Integer.valueOf(env.getProperty("spring.datasource.dbcp2.max-idle")));
        dataSource.setInitialSize(Integer.valueOf(env.getProperty("spring.datasource.dbcp2.initial-size")));
        return dataSource;
    }

    @Bean(name = "h2Datasource")
    public BasicDataSource h2DataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(env.getProperty("spring.h2.datasource.driver-class-name"));
        dataSource.setUrl(env.getProperty("spring.h2.datasource.url"));
        dataSource.setUsername(env.getProperty("spring.h2.datasource.username"));
        dataSource.setPassword(env.getProperty("spring.h2.datasource.password"));

        Resource initData = new ClassPathResource("scripts/inmem.sql");
        DatabasePopulator databasePopulator = new ResourceDatabasePopulator(initData);
        DatabasePopulatorUtils.execute(databasePopulator, dataSource);

        return dataSource;
    }

Here datasource for PostgreSQL is a primary bean. In my several tests I would like to run a script against h2 database. For that I am trying to use @Sql annotation. However, if I use @Sql, it runs script against pgDatasource. I could configure h2 as a primary bean for those tests, but test methods' bodies are dependent on the configuration where pgDatasource is a primary bean.

Test sample:

@Test
@Sql(scripts = "/clean_login_attempts.sql", executionPhase = AFTER_TEST_METHOD)
void loginAttemptsIncrementTheCount() throws Exception {
    unsuccessfulLoginRequest();
    unsuccessfulLoginRequest();
    unsuccessfulLoginRequest();

    LoginAttempt loginAttempt = loginAttemptService.getAttempt("admin");
    assertEquals(3, loginAttempt.getAttempt());
}

Is it possible to configure datasource for org.springframework.test.context.jdbc.Sql annotation?


Solution

  • Adding

    config = @SqlConfig(dataSource = "h2Datasource", transactionManager = "h2tx") 
    

    solved the issue.

    @Test
    @Sql(scripts = "/clean_login_attempts.sql", 
         executionPhase = AFTER_TEST_METHOD, 
         config = @SqlConfig(dataSource = "h2Datasource", transactionManager = "h2tx"))
    void loginAttemptsIncrementTheCount() throws Exception {
        unsuccessfulLoginRequest();
        unsuccessfulLoginRequest();
        unsuccessfulLoginRequest();
    
        LoginAttempt loginAttempt = loginAttemptService.getAttempt("admin");
        assertEquals(3, loginAttempt.getAttempt());
    }