如何在每个测试方法之前和之后执行sql脚本
Posted
技术标签:
【中文标题】如何在每个测试方法之前和之后执行sql脚本【英文标题】:How to execute sql script before and after each test method 【发布时间】:2020-10-25 21:55:49 【问题描述】:spring中有一个@Sql
注解,允许在测试方法前后执行sql代码:
@Test
@Sql("init.sql")
@Sql(scripts = "clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public void someTest()
但是,我有几种测试方法,我想提供与上述测试相同的干净环境,并且我不想为每个测试重复相同的 @Sql
注释。如何为所有方法做一次?例如:
// JPA and Spring other test annotations
@Sql("init.sql")
@Sql(scripts = "clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public class TestClass
// init.sql executed before every test, clean.sql executed after every test
【问题讨论】:
【参考方案1】:确实,当您将@Sql
放在class
上时,sql 脚本将在该类中定义的每个测试之前和之后执行,更具体地说,在@Before
之前和@After
方法之后.所以,
// JPA and Spring other test annotations
@Sql("init.sql")
@Sql(scripts = "clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
public class TestClass
// init.sql executed before every test, clean.sql executed after every test
将根据@Sql
定义工作:
@Target(ElementType.TYPE, ElementType.METHOD)
/// other annotations
public @interface Sql
//
【讨论】:
【参考方案2】:如果我的理解是正确的,你是想执行一个init脚本把DB置于某个状态,然后在每个测试方法之前确保DB回到那个状态,对吧?
那么最简单的解决方案是使用@Transactional
。默认情况下,Spring Boot 会自动回滚 @Transactional
-annotated 测试的测试事务,从而将 DB 重置为原始状态。
不过,有两个缺点应该考虑:
@Transactional
表示将存在一个跨越测试方法的整个执行的事务,测试的服务方法通常会加入该事务。因此,不能依靠测试本身来验证生产代码中事务边界的正确性(例如,LazyInitializationException
s 可能被这个“外部”事务覆盖)
除非必要,否则不会刷新持久性上下文,这意味着某些问题(例如违反数据库约束)不会出现。我倾向于使用最后机会冲洗来解决这个问题,如下所示:
@After
public void flushContext()
if (TransactionSynchronizationManager.isActualTransactionActive())
entityManager.flush();
【讨论】:
回答第一个问题:是的,这正是我想要实现的。我使用@DataJpaTest
,所以无论如何都会使用@Transactional
。我想运行 init 和 clear 脚本的原因是因为无法回滚的序列,所以在 init.sql 和 clean.sql 中我删除序列并重新创建它们从而具有完全干净的状态。感谢您对@Transactional
的第一条评论非常好。以上是关于如何在每个测试方法之前和之后执行sql脚本的主要内容,如果未能解决你的问题,请参考以下文章
VS2010 负载测试:如何执行在每次负载测试之前运行一次的自定义操作