Sunday, September 23, 2012

Spring 3 - JavaConfig: Unit Testing using a Different Profile

In unit tests, you should not connect to an external database or webservice. Instead, you should use an in-memory database like hsqldb and mock any other external system dependencies. In order to do so, you need to inject test beans into the Spring container instead of using real ones. This example shows how you can use a different configuration for unit testing using Spring Java-based configuration.

Let's start with the following configuration:

/**
 * Configuration for an external oracle database.
 */
@Configuration
public class DatabaseConfig {

  @Bean
  public DataSource personDataSource() {
    DataSource ds = new org.apache.commons.dbcp.BasicDataSource();
    ds.setDriverClassName("oracle.jdbc.driver.OracleDriver");
    ds.setUrl("jdbc:oracle:thin:@firefly:1521:HRP2");
    ds.setUsername("scott");
    ds.setPassword("tiger");
    return ds;
  }
}

/**
 * Main application config.
 */
@Configuration
@Import(DatabaseConfig.class)
public class AppConfig {

  @Bean
  public PersonDao personDao() {
    return new PersonDao(personDataSource());
  }
}
In order to use a different database for your unit tests, you need to create a separate unit test database configuration as shown below. This configuration returns an HSQL data source and, more importantly, is decorated with a @Profile annotation which indicates that it will be only be used when the "unit-test" profile is active.
/**
 * Configuration for an embedded HSQL database used by unit tests.
 */
@Configuration
@Profile("unit-test")
public class UnitTestDatabaseConfig extends DatabaseConfig {

  @Override
  @Bean
  public DataSource personDataSource() {
    return new EmbeddedDatabaseBuilder()
               .setType(EmbeddedDatabaseType.HSQL)
               .addScript("person.sql")
               .build();
  }
}
Now, write your unit test as shown below. The @ActiveProfiles annotation tells Spring which profile to use when loading beans for the test classes. Since it is set to "unit-test", the HSQL DataSource will be used.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { AppConfig.class, UnitTestDatabaseConfig.class })
@ActiveProfiles("unit-test")
public class PersonDaoTest {

  @Autowired
  private PersonDao personDao;

  @Test
  public void testGetPerson() {
    Person p = personDao.getPerson("Joe");
  }
}

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.