同时Spring Boot提供了和Flyway的集成支持,能够方便的管理开发过程中产生的SQL文件,配合Spring已经提供的工具能够更方便地在测试之前初始化数据库以及测试之后清空数据库。
本章节为了方便起见,本章节使用了H2作为测试数据库。
注意:在真实的开发环境中,集成测试用数据库应该和最终的生产数据库保持一致,这是因为不同数据库的对于SQL不是完全相互兼容的,如果不注意这一点,很有可能出现集成测试通过,但是上了生产环境却报错的问题。
因为是集成测试,所以我们使用了maven-failsafe-plugin来跑,它和maven-surefire-plugin的差别在于,maven-failsafe-plugin只会搜索*IT.java来跑测试,而maven-surefire-plugin只会搜索*Test.java来跑测试。
如果想要在maven打包的时候跳过集成测试,只需要mvn clean install -DskipITs。
被测试类
先介绍一下被测试的类。
Foo.java: publicclassFoo{ privateStringname; publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } } FooRepositoryImpl.java: @Repository publicclassFooRepositoryImplimplementsFooRepository{ privateJdbcTemplatejdbcTemplate; @Override publicvoidsave(Foofoo){ jdbcTemplate.update("INSERTINTOFOO(name)VALUES(?)",foo.getName()); } @Override publicvoiddelete(Stringname){ jdbcTemplate.update("DELETEFROMFOOWHERENAME=?",name); } @Autowired publicvoidsetJdbcTemplate(JdbcTemplatejdbcTemplate){ this.jdbcTemplate=jdbcTemplate; } } |
例子1:不使用Spring Testing提供的工具
Spring_1_IT_Configuration.java: @Configuration @ComponentScan(basePackageClasses = FooRepository.class) public class Spring_1_IT_Configuration { @Bean(destroyMethod = "shutdown") public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .generateUniqueName(true) .setType(EmbeddedDatabaseType.H2) .setScriptEncoding("UTF-8") .ignoreFailedDrops(true) .addScript("classpath:me/chanjar/domain/foo-ddl.sql") .build(); } @Bean public JdbcTemplate jdbcTemplate() { return new JdbcTemplate(dataSource()); } } |
在Spring_1_IT_Configuration中,我们定义了一个H2的DataSource Bean,并且构建了JdbcTemplate Bean。
注意看addScript(“classpath:me/chanjar/domain/foo-ddl.sql”)这句代码,我们让EmbeddedDatabase执行foo-ddl.sql脚本来建表:
CREATE TABLE FOO ( name VARCHAR2(100) ); Spring_1_IT.java: @ContextConfiguration(classes = Spring_1_IT_Configuration.class) public class Spring_1_IT extends AbstractTestNGSpringContextTests { @Autowired private FooRepository fooRepository; @Autowired private JdbcTemplate jdbcTemplate; @Test public void testSave() { Foo foo = new Foo(); foo.setName("Bob"); fooRepository.save(foo); assertEquals( jdbcTemplate.queryForObject("SELECT count(*) FROM FOO", Integer.class), Integer.valueOf(1) ); } @Test(dependsOnMethods = "testSave") public void testDelete() { assertEquals( jdbcTemplate.queryForObject("SELECT count(*) FROM FOO", Integer.class), Integer.valueOf(1) ); Foo foo = new Foo(); foo.setName("Bob"); fooRepository.save(foo); fooRepository.delete(foo.getName()); assertEquals( jdbcTemplate.queryForObject("SELECT count(*) FROM FOO", Integer.class), Integer.valueOf(0) ); } } |
在这段测试代码里可以看到,我们分别测试了FooRepository的save和delete方法,并且利用JdbcTemplate来验证数据库中的结果。
例子2:使用Spring Testing提供的工具
在这个例子里,我们会使用JdbcTestUtils来辅助测试。
Spring_2_IT_Configuration.java: @Configuration @ComponentScan(basePackageClasses = FooRepository.class) public class Spring_2_IT_Configuration { @Bean public DataSource dataSource() { EmbeddedDatabase db = new EmbeddedDatabaseBuilder() .generateUniqueName(true) .setType(EmbeddedDatabaseType.H2) .setScriptEncoding("UTF-8") .ignoreFailedDrops(true) .addScript("classpath:me/chanjar/domain/foo-ddl.sql") .build(); return db; } @Bean public JdbcTemplate jdbcTemplate() { return new JdbcTemplate(dataSource()); } @Bean public PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } } |