在测试运行时,测试类中 @Transactional 注解,会导致测试中 Entity 数据的操作都是在内存中完成,最终并不会进行 commit 操作,也就是不会将 Entity 数据进行持久化操作,从而导致测试的行为和真实应用的行为不一致。

事务管理在应用开发中是种不可或缺的设计,它是数据库持久化处理的一种标准。我们知道,应用程序开发离不开对数据的CRUD(增删改查),事务的ACID可以更好保证数据的完整性,保证相关数据的同生共死。单个事务生命周期主要分为三个阶段,BEGIN TRANSACTION -> COMMIT TRANSACTION -> ROLLBACK TRANSACTION

Spring Boot事务的使用分为命令式声明式常用的方式是声明式注解(@Transactional)。事务管理既可以在应用层使用,也可以在测试中使用。

为了保证测试之间的相互独立,测试之间数据不会被相互影响。也许你写过这样的测试:

@SpringBootTest
@ActiveProfiles("test")
@Transactional
public class UserControllerTest { }

@Transactional 通过将数据持久化操作截断,来解决测试之间相互对立,数据相互不影响的问题。然而这样方式会有副作用,就是数据持久化的过程不再真实,没有了commit的过程。从而会导致:

  • 无法保证 Entity 之间关联关系,唯一索引和主外键关联的准确性
  • 无法保证 Entity 创建时间、更新时间和版本化(乐观锁)的赋值逻辑的准确性
  • 无法保证 Entity 中有 @Transient 注解的属性的赋值逻辑的准确性
  • 测试的数据不是真实场景存在的问题
  • 测试中,单个事务中的准备数据,无法在多线程中共享。

......

然后 Spring 在测试问题域中引入事务管理初衷是什么?为了解决什么问题才需要将它引入?官方文档介绍 Transaction management

按照官方文档意思,为了解决测试运行时,程序访问真实的数据库,改变数据的状态,从而影响到后续的测试问题。

其实这里应该批判性思维一下,为什么测试运行时,需要访问真实的数据库?为什么测试之间的数据会相互影响?
对于每个测试来说,每次运行前都应该有干净的上下文,或者说独立的上下文,有数据清理和准备的过程,测试与测试之间相互隔离。也就是说,为什么测试不能用内存数据库或者嵌入式数据库?为什么不是每个测试运行前清理一下数据库中的数据,保证测试用例运行前的一方净土,不被上个测试数据影响?

答案当然是,可以!!!

写在最后

如何做?实现一个 TruncateDatabaseService,只删除表的数据,不删除表的结果。 在测试基类的@BeforeEach,执行 truncate。源码Truncate Database:

TruncateDatabaseBasicOnHibernateService
TruncateDatabaseBasicOnMybatisService

原文链接

不要在 Spring Boot 集成测试中使用 @Transactional相关推荐

  1. Spring Boot集成测试中@ContextConfiguration和@SpringApplicationConfiguration之间的区别

    即使同时使用@ContextConfiguration和@SpringApplicationConfiguration批注以及SpringJUnit4ClassRunner来指定如何加载Spring应 ...

  2. 在Spring Boot测试中使用Testcontainer进行数据库集成测试

    在此博客文章中,我想演示如何在Spring Boot测试中集成Testcontainer以便与数据库一起运行集成测试. 我没有使用Testcontainers的Spring Boot模块. 如何与他们 ...

  3. 在Spring Boot项目中使用Spock框架

    转载:https://www.jianshu.com/p/f1e354d382cd Spock框架是基于Groovy语言的测试框架,Groovy与Java具备良好的互操作性,因此可以在Spring B ...

  4. Spring Boot JPA 中transaction的使用

    文章目录 @Transactional的实现 @Transactional的使用 Transaction的传播级别 REQUIRED SUPPORTS MANDATORY NEVER NOT_SUPP ...

  5. Spring Boot JPA中java 8 的应用

    文章目录 Optional Stream API CompletableFuture Spring Boot JPA中java 8 的应用 上篇文章中我们讲到了如何在Spring Boot中使用JPA ...

  6. Spring Boot 声明式事务 @Transactional 的使用

    1.Spring Boot 项目中使用事务 首先使用 @EnableTransactionManagement 注解开启事务支持,然后在需要事务管理的 public 方法上添加注解 @Transact ...

  7. Guava Cache本地缓存在 Spring Boot应用中的实践

    概述 在如今高并发的互联网应用中,缓存的地位举足轻重,对提升程序性能帮助不小.而 3.x开始的 Spring也引入了对 Cache的支持,那对于如今发展得如火如荼的 Spring Boot来说自然也是 ...

  8. spring boot 项目源码_Spring Boot2 系列教程(三)理解 Spring Boot 项目中的 parent

    前面和大伙聊了 Spring Boot 项目的三种创建方式,这三种创建方式,无论是哪一种,创建成功后,pom.xml 坐标文件中都有如下一段引用: <parent><groupId& ...

  9. Spring Boot 配置中的敏感信息如何保护?

    在之前的系列教程中,我们已经介绍了非常多关于Spring Boot配置文件中的各种细节用法,比如:参数间的引用.随机数的应用.命令行参数的使用.多环境的配置管理等等. 这些配置相关的知识都是Sprin ...

最新文章

  1. python使用openweathermap API获取全世界主要城市天气信息
  2. 生日快乐程序_亲爱的陕师大:75岁生日快乐!一起走过师大时光,在线生成你的师大印迹!...
  3. 【Android 逆向】Android 权限 ( ro.product.cpu.abi 属性 | ro.zygote 属性 | dhcp.eth0 属性 | net.* 属性 )
  4. 邮件服务器postfix+cyrus
  5. mysql savepoint是什么_Mysql中的隐式COMMIT以及Savepoints的作用
  6. [css] 为什么float会导致父元素塌陷
  7. php curl curlopt_getfields,PHP中CURL的CURLOPT_POSTFIELDS参数使用细节
  8. Redis 阶段总结
  9. Numpy的使用(2)
  10. 进程queue和线程queue
  11. 计算机在多媒体领域的应用论文题目,多媒体技术论文题目
  12. echarts官网在线编辑的图表如何导出svg
  13. sql server设置星期一为每周第一天
  14. 2021-01-19 :在pycharm中创建包含anaconda中各种库的环境
  15. 易简无人机巡检照片处理系统(一) —— 巡检作业流程
  16. 学计算机的女生容易脱单,最容易让男生脱单的5个大学专业,特别是第3个,女生会倒追你!...
  17. 微信网络营销 你造吗?
  18. 后台录屏、应用外录屏、跨应用录屏、直播屏幕、录屏扩展(ios)
  19. matlab中的a逆怎么使用方法,在MATLAB中,求矩阵A逆矩阵可用命令( )。
  20. Qt QLineEdit单行输入框用法详解

热门文章

  1. 精通CSS+DIV基础总结(三)
  2. 播放器03:以文件夹的形式添加整个文件夹里面的文件到播放列表,播放刚加进来的第一首歌曲,默认顺序播放...
  3. Facade模式——设计模式学习笔记
  4. ISIS和OSPF的比较
  5. pythonのgevent同步异步区别
  6. 为更好提高客户对产品的满意度需要搞好站点建设问题
  7. Light OJ 1012
  8. mysql中文乱码的一点理解
  9. 2013.11.13
  10. PowerDesigner教程系列(四)概念数据模型