Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 484
valijon Avatar asked Dec 05 '18 05:12

valijon


People also ask

How to configure a data source for testing in spring?

Configuring a data source in Spring requires defining a bean of type DataSource, either manually or, if using Spring Boot, through standard application properties. In this quick tutorial, we're going to take a look at several ways to configure a separate data source for testing in Spring. 2.

How to use @SQL annotation in Spring Integration Test?

The Spring @Sql annotation executes SQL scripts and SQL statements against a database in Spring integration test. The @Sql annotation is used at class level as well as method level. By default, method level @Sql declarations override class level @Sql declarations and we can change this behavior by configuring @SqlMergeMode.

How to parse SQL scripts in Spring Integration Test class?

Find the print screen of the output. The Spring @SqlConfig determines how to parse SQL scripts configured via @Sql annotation. The @SqlConfig can be annotated at class level of Spring test class and that will serve as global configuration for all SQL scripts in that integration test class i.e. global scope.

How to configure a separate DataSource for testing?

Another way we could configure a separate DataSource for testing is by leveraging Spring Profiles to define a DataSource bean that is only available in a test profile. For this, we can use a .properties file as before, or we can write the values in the class itself.


1 Answers

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());
}
like image 158
valijon Avatar answered Oct 13 '22 17:10

valijon