Spring Test Framework提供了对JDBC的支持,可以或许让我们很利便对干系型数据库做集成测试。
同时Spring Boot提供了和Flyway的集成支持,可以或许利便的打点开拓进程中发生的SQL文件,共同Spring已经提供的东西可以或许更利便地在测试之前初始化数据库以及测试之后清空数据库。
本章节为了利便起见,本章节利用了p作为测试数据库。
留意:在真实的开拓情况中,集成测试用数据库应该和最终的出产数据库保持一致,这是因为差异数据库的对付SQL不是完全彼此兼容的,假如不留意这一点,很有大概呈现集成测试通过,可是上了出产情况却报错的问题。
因为是集成测试,所以我们利用了maven-failsafe-plugin来跑,它和maven-surefire-plugin的不同在于,maven-failsafe-plugin只会搜索*IT.java来跑测试,而maven-surefire-plugin只会搜索*Test.java来跑测试。
假如想要在maven打包的时候跳过集成测试,只需要mvn clean install -DskipITs。
被测试类
先先容一下被测试的类。
Foo.java:
public class Foo { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
FooRepositoryImpl.java:
@Repository public class FooRepositoryImpl implements FooRepository { private JdbcTemplate jdbcTemplate; @Override public void save(Foo foo) { jdbcTemplate.update("INSERT INTO FOO(name) VALUES (?)", foo.getName()); } @Override public void delete(String name) { jdbcTemplate.update("DELETE FROM FOO WHERE NAME = ?", name); } @Autowired public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { 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.p) .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中,我们界说了一个p的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.p) .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()); } }
这里和例子1的区别在于,昆山软件公司,我们提供了一个PlatformTransactionManager Bean,昆山软件开发,这是因为在下面的测试代码里的AbstractTransactionalTestNGSpringContextTests需要它。