Spring4.1新特性——数据库集成测试

简介: <p>在Spring 4.1之前我们在准备测试数据时可能通过继承AbstractTransactionalJUnit4SpringContextTests,然后调用executeSqlScript()进行测试,其中存在一个主要问题:如果要同时执行多个数据源的初始化就靠不住了,而且使用起来也不是特别便利,Spring4.1提供了@Sql注解来完成这个任务。</p> <p> </p> <p

在Spring 4.1之前我们在准备测试数据时可能通过继承AbstractTransactionalJUnit4SpringContextTests,然后调用executeSqlScript()进行测试,其中存在一个主要问题:如果要同时执行多个数据源的初始化就靠不住了,而且使用起来也不是特别便利,Spring4.1提供了@Sql注解来完成这个任务。

 

1、初始化Spring配置: 

Java代码   收藏代码
  1. <jdbc:embedded-database id="dataSource1" type="HSQL"/>  
  2. <jdbc:embedded-database id="dataSource2" type="HSQL"/>  
  3.   
  4. <bean id="txManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
  5.     <property name="dataSource" ref="dataSource1"/>  
  6. </bean>  
  7.   
  8. <bean id="txManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
  9.     <property name="dataSource" ref="dataSource2"/>  
  10. </bean>  

此处使用jdbc:embedded嵌入数据库来完成测试,数据库使用HSQL。

 

2、 方法级别的@Sql

Java代码   收藏代码
  1. @RunWith(SpringJUnit4ClassRunner.class)  
  2. @FixMethodOrder(MethodSorters.NAME_ASCENDING)  
  3. @ContextConfiguration(value = "classpath:spring-datasource.xml")  
  4. @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)  
  5. public class MethodLevelSqlTest {  
  6.     private JdbcTemplate jdbcTemplate1;  
  7.     private JdbcTemplate jdbcTemplate2;  
  8.     @Autowired  
  9.     @Qualifier("dataSource1")  
  10.     public void setDataSource1(DataSource dataSource1) {  
  11.         this.jdbcTemplate1 = new JdbcTemplate(dataSource1);  
  12.     }  
  13.     @Autowired  
  14.     @Qualifier("dataSource2")  
  15.     public void setDataSource2(DataSource dataSource2) {  
  16.         this.jdbcTemplate2 = new JdbcTemplate(dataSource2);  
  17.     }  
  18.   
  19.   
  20.     @Test  
  21.     @Sql(value = {"classpath:schema.sql""classpath:init-data.sql""classpath:updated-data.sql"},  
  22.             config =  
  23.             @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",  
  24.                     dataSource = "dataSource1", transactionManager = "txManager1"))  
  25.     public void test01_simple() {  
  26.         Assert.assertEquals(  
  27.                 Integer.valueOf(3),  
  28.                 jdbcTemplate1.queryForObject("select count(1) from users", Integer.class));  
  29.     }  
  30.   
  31.   
  32.     @Test  
  33.     @Sql(value = {"classpath:schema.sql""classpath:init-data.sql"},  
  34.             config =  
  35.             @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",  
  36.                     dataSource = "dataSource2", transactionManager = "txManager2"))  
  37.     public void test02_simple() {  
  38.         Assert.assertEquals(  
  39.                 Integer.valueOf(2),  
  40.                 jdbcTemplate2.queryForObject("select count(1) from users", Integer.class));  
  41.     }  
  42.   
  43. }  

方法级别的@Sql在每个方法上都会执行。其中@Sql可以指定多个sql文件,然后通过@SqlConfig指定其编码、分隔符、注释前缀、使用哪个数据源和事务管理器。

 

 

3、类级别的@Sql

Java代码   收藏代码
  1. @RunWith(SpringJUnit4ClassRunner.class)  
  2. @FixMethodOrder(MethodSorters.NAME_ASCENDING)  
  3. @ContextConfiguration(value = "classpath:spring-datasource.xml")  
  4. @Sql(value = {"classpath:schema.sql""classpath:init-data.sql""classpath:updated-data.sql"},  
  5.         config =  
  6.         @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",  
  7.                 dataSource = "dataSource1", transactionManager = "txManager1"))  
  8. @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)  
  9. public class ClassLevelSqlTest {  
  10.   
  11.     private JdbcTemplate jdbcTemplate1;  
  12.     @Autowired  
  13.     @Qualifier("dataSource1")  
  14.     public void setDataSource1(DataSource dataSource1) {  
  15.         this.jdbcTemplate1 = new JdbcTemplate(dataSource1);  
  16.     }  
  17.   
  18.     @Test  
  19.     public void test01_simple() {  
  20.         Assert.assertEquals(  
  21.                 Integer.valueOf(3),  
  22.                 jdbcTemplate1.queryForObject("select count(1) from users", Integer.class));  
  23.     }  
  24. }  

类级别的对整个测试用例中的每个方法都起作用。 

 

4、指定多个@Sql 

Java8之前需要使用@SqlGroup,而Java8之后直接使用多个@Sql注解即可。

Java代码   收藏代码
  1. @RunWith(SpringJUnit4ClassRunner.class)  
  2. @FixMethodOrder(MethodSorters.NAME_ASCENDING)  
  3. @ContextConfiguration(value = "classpath:spring-datasource.xml")  
  4. @Transactional()  
  5. @SqlGroup(  
  6.         {  
  7.                 @Sql(value = {"classpath:schema.sql""classpath:init-data.sql""classpath:updated-data.sql"},  
  8.                         config =  
  9.                         @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",  
  10.                                 dataSource = "dataSource1", transactionManager = "txManager1")),  
  11.                 @Sql(value = {"classpath:schema.sql""classpath:init-data.sql"},  
  12.                         config =  
  13.                         @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",  
  14.                                 dataSource = "dataSource2", transactionManager = "txManager2"))  
  15.         }  
  16. )  
  17.   
  18. @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)  
  19. public class ClassLevelSqlGroupTest {  
  20.   
  21.     private JdbcTemplate jdbcTemplate1;  
  22.     private JdbcTemplate jdbcTemplate2;  
  23.     @Autowired  
  24.     @Qualifier("dataSource1")  
  25.     public void setDataSource1(DataSource dataSource1) {  
  26.         this.jdbcTemplate1 = new JdbcTemplate(dataSource1);  
  27.     }  
  28.     @Autowired  
  29.     @Qualifier("dataSource2")  
  30.     public void setDataSource2(DataSource dataSource2) {  
  31.         this.jdbcTemplate2 = new JdbcTemplate(dataSource2);  
  32.     }  
  33.   
  34.   
  35.     @Test  
  36.     @Transactional()  
  37.     @Sql(value = {"classpath:schema.sql""classpath:init-data.sql""classpath:updated-data.sql"},  
  38.             config =  
  39.             @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",  
  40.                     dataSource = "dataSource1", transactionManager = "txManager1"))  
  41.     public void test01_simple() {  
  42.         Assert.assertEquals(  
  43.                 Integer.valueOf(3),  
  44.                 jdbcTemplate1.queryForObject("select count(1) from users", Integer.class));  
  45.     }  
  46.   
  47.   
  48.     @Test  
  49.     @Transactional()  
  50.     @Sql(value = {"classpath:schema.sql""classpath:init-data.sql"},  
  51.             config =  
  52.             @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",  
  53.                     dataSource = "dataSource2", transactionManager = "txManager2"))  
  54.     public void test02_simple() {  
  55.         Assert.assertEquals(  
  56.                 Integer.valueOf(2),  
  57.                 jdbcTemplate2.queryForObject("select count(1) from users", Integer.class));  
  58.     }  
  59.   
  60. }  

 

也可以通过元注解把注解合并:

Java代码   收藏代码
  1. @SqlGroup(  
  2.         {  
  3.                 @Sql(value = {"classpath:schema.sql""classpath:init-data.sql""classpath:updated-data.sql"},  
  4.                         config =  
  5.                         @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",  
  6.                                 dataSource = "dataSource1", transactionManager = "txManager1")),  
  7.                 @Sql(value = {"classpath:schema.sql""classpath:init-data.sql"},  
  8.                         config =  
  9.                         @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",  
  10.                                 dataSource = "dataSource2", transactionManager = "txManager2"))  
  11.         }  
  12. )  
  13. @Retention(RUNTIME)  
  14. @Target(TYPE)  
  15. @interface CompositeSqlGroup {  
  16. }  

直接使用@CompositeSqlGroup注解即可。

 

5、事务

Java代码   收藏代码
  1. @RunWith(SpringJUnit4ClassRunner.class)  
  2. @FixMethodOrder(MethodSorters.NAME_ASCENDING)  
  3. @ContextConfiguration(value = "classpath:spring-datasource.xml")  
  4. @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)  
  5. public class TransactionalTest {  
  6.     private JdbcTemplate jdbcTemplate1;  
  7.     private JdbcTemplate jdbcTemplate2;  
  8.     @Autowired  
  9.     @Qualifier("dataSource1")  
  10.     public void setDataSource1(DataSource dataSource1) {  
  11.         this.jdbcTemplate1 = new JdbcTemplate(dataSource1);  
  12.     }  
  13.     @Autowired  
  14.     @Qualifier("dataSource2")  
  15.     public void setDataSource2(DataSource dataSource2) {  
  16.         this.jdbcTemplate2 = new JdbcTemplate(dataSource2);  
  17.     }  
  18.   
  19.   
  20.     @Test  
  21.     @Transactional("txManager1")  
  22.     @Sql(value = {"classpath:schema.sql""classpath:init-data.sql""classpath:updated-data.sql"},  
  23.             config =  
  24.             @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",  
  25.                     dataSource = "dataSource1", transactionManager = "txManager1"))  
  26.     public void test01_simple() {  
  27.         //判断是在事务中执行  
  28.         Assert.assertTrue(TransactionSynchronizationManager.isActualTransactionActive());  
  29.         Assert.assertTrue(TestTransaction.isActive());  
  30.         Assert.assertEquals(  
  31.                 Integer.valueOf(3),  
  32.                 jdbcTemplate1.queryForObject("select count(1) from users", Integer.class));  
  33.     }  
  34.   
  35.   
  36.     @Test  
  37.     @Transactional("txManager2")  
  38.     @Sql(value = {"classpath:schema.sql""classpath:init-data.sql"},  
  39.             config =  
  40.             @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",  
  41.                     dataSource = "dataSource2", transactionManager = "txManager2"))  
  42.     public void test02_simple() {  
  43.         Assert.assertEquals(  
  44.                 Integer.valueOf(2),  
  45.                 jdbcTemplate2.queryForObject("select count(1) from users", Integer.class));  
  46.     }  
  47.   
  48.   
  49.     @Test  
  50.     @Transactional("txManager2")  
  51.     @Sql(value = {"classpath:schema.sql""classpath:init-data.sql"},  
  52.             config =  
  53.             @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",  
  54.                     dataSource = "dataSource2", transactionManager = "txManager2"))  
  55.     public void test03_simple() {  
  56.         Assert.assertEquals(  
  57.                 Integer.valueOf(2),  
  58.                 jdbcTemplate2.queryForObject("select count(1) from users", Integer.class));  
  59.         TestTransaction.flagForRollback();  
  60.     }  
  61.   
  62.     @Rule  
  63.     public TestName testName = new TestName();  
  64.     @AfterTransaction  
  65.     public void afterTransaction() {  
  66.         System.out.println(testName.getMethodName());  
  67.         if("test03_simple".equals(testName.getMethodName())) {  
  68.             Assert.assertEquals(  
  69.                     Integer.valueOf(0),  
  70.                     jdbcTemplate2.queryForObject("select count(1) from users", Integer.class));  
  71.         }  
  72.     }  
  73. }  

可以使用//判断是在事务中执行TransactionSynchronizationManager.isActualTransactionActive()或TestTransaction.isActive()来判断是否是在事务中执行;通过TestTransaction.flagForRollback();来回滚事务;在测试用例中@AfterTransaction来断言回滚后数据没有插入。


本文转自http://jinnianshilongnian.iteye.com/blog/2106184

目录
相关文章
|
6天前
|
SQL 关系型数据库 MySQL
stream-query多数据库进行CI测试
stream-query多数据库进行CI测试
14 0
|
20天前
|
关系型数据库 分布式数据库 数据库
成都晨云信息技术完成阿里云PolarDB数据库产品生态集成认证
近日,成都晨云信息技术有限责任公司(以下简称晨云信息)与阿里云PolarDB PostgreSQL版数据库产品展开产品集成认证。测试结果表明,晨云信息旗下晨云-站群管理系统(V1.0)与阿里云以下产品:开源云原生数据库PolarDB PostgreSQL版(V11),完全满足产品兼容认证要求,兼容性良好,系统运行稳定。
|
1月前
|
Oracle 关系型数据库 分布式数据库
分布式数据库集成解决方案
分布式数据库集成解决方案
198 0
|
28天前
|
Java Spring
使用JDBCTemplate实现与Spring结合,方法公用 ——测试(EmpDaoImplTest)
使用JDBCTemplate实现与Spring结合,方法公用 ——测试(EmpDaoImplTest)
8 0
|
2月前
|
安全 Java 数据库
后端进阶之路——万字总结Spring Security与数据库集成实践(五)
后端进阶之路——万字总结Spring Security与数据库集成实践(五)
|
2月前
|
设计模式 前端开发 Java
玩转Spring—Spring5新特性之Reactive响应式编程实战
玩转Spring—Spring5新特性之Reactive响应式编程实战
59 0
|
28天前
|
Java Spring
使用spring实现邮件的发送(含测试,源码,注释)
使用spring实现邮件的发送(含测试,源码,注释)
7 0
|
29天前
|
Java 数据库连接 数据库
Spring Boot整合MyBatis Plus集成多数据源轻松实现数据读写分离
Spring Boot整合MyBatis Plus集成多数据源轻松实现数据读写分离
26 2
|
1月前
|
消息中间件 Kafka Linux
Kafka【付诸实践 03】Offset Explorer Kafka 的终极 UI 工具安装+简单上手+关键特性测试(一篇学会使用 Offset Explorer)
【2月更文挑战第21天】Kafka【付诸实践 03】Offset Explorer Kafka 的终极 UI 工具安装+简单上手+关键特性测试(一篇学会使用 Offset Explorer)
148 2
|
1月前
|
监控 NoSQL Java
Spring Boot集成Redis启动失败【Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool2.impl.G】
Spring Boot集成Redis启动失败【Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool2.impl.G】