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

目录
相关文章
|
3月前
|
Java 测试技术 开发者
必学!Spring Boot 单元测试、Mock 与 TestContainer 的高效使用技巧
【10月更文挑战第18天】 在现代软件开发中,单元测试是保证代码质量的重要手段。Spring Boot提供了强大的测试支持,使得编写和运行测试变得更加简单和高效。本文将深入探讨Spring Boot的单元测试、Mock技术以及TestContainer的高效使用技巧,帮助开发者提升测试效率和代码质量。
350 2
|
3月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
63 4
|
3月前
|
Java Maven Docker
gitlab-ci 集成 k3s 部署spring boot 应用
gitlab-ci 集成 k3s 部署spring boot 应用
|
3月前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
57 0
|
1月前
|
XML Java API
Spring Boot集成MinIO
本文介绍了如何在Spring Boot项目中集成MinIO,一个高性能的分布式对象存储服务。主要步骤包括:引入MinIO依赖、配置MinIO属性、创建MinIO配置类和服务类、使用服务类实现文件上传和下载功能,以及运行应用进行测试。通过这些步骤,可以轻松地在项目中使用MinIO的对象存储功能。
|
2月前
|
消息中间件 Java Kafka
什么是Apache Kafka?如何将其与Spring Boot集成?
什么是Apache Kafka?如何将其与Spring Boot集成?
72 5
|
2月前
|
Java 测试技术 API
详解Swagger:Spring Boot中的API文档生成与测试工具
详解Swagger:Spring Boot中的API文档生成与测试工具
49 4
|
2月前
|
消息中间件 Java Kafka
Spring Boot 与 Apache Kafka 集成详解:构建高效消息驱动应用
Spring Boot 与 Apache Kafka 集成详解:构建高效消息驱动应用
56 1
|
2月前
|
数据库连接 Go 数据库
Go语言中的错误注入与防御编程。错误注入通过模拟网络故障、数据库错误等,测试系统稳定性
本文探讨了Go语言中的错误注入与防御编程。错误注入通过模拟网络故障、数据库错误等,测试系统稳定性;防御编程则强调在编码时考虑各种错误情况,确保程序健壮性。文章详细介绍了这两种技术在Go语言中的实现方法及其重要性,旨在提升软件质量和可靠性。
39 1
|
2月前
|
Web App开发 定位技术 iOS开发
Playwright 是一个强大的工具,用于在各种浏览器上测试应用,并模拟真实设备如手机和平板。通过配置 `playwright.devices`,可以轻松模拟不同设备的用户代理、屏幕尺寸、视口等特性。此外,Playwright 还支持模拟地理位置、区域设置、时区、权限(如通知)和配色方案,使测试更加全面和真实。例如,可以在配置文件中设置全局的区域设置和时区,然后在特定测试中进行覆盖。同时,还可以动态更改地理位置和媒体类型,以适应不同的测试需求。
Playwright 是一个强大的工具,用于在各种浏览器上测试应用,并模拟真实设备如手机和平板。通过配置 `playwright.devices`,可以轻松模拟不同设备的用户代理、屏幕尺寸、视口等特性。此外,Playwright 还支持模拟地理位置、区域设置、时区、权限(如通知)和配色方案,使测试更加全面和真实。例如,可以在配置文件中设置全局的区域设置和时区,然后在特定测试中进行覆盖。同时,还可以动态更改地理位置和媒体类型,以适应不同的测试需求。
117 1