不要在Spring单元测试中使用 @Transactional注解

时间:2022-07-25
本文章向大家介绍不要在Spring单元测试中使用 @Transactional注解,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、核心问题

在单元测试时,测试类中 @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 注解的属性的赋值逻辑的准确性
  • 测试的数据不是真实场景存在的问题
  • 测试中,单个事务中的准备数据,无法在多线程中共享。

喜欢 (7)or分享 (0)