繁体   English   中英

每种测试方法前后如何执行 sql 脚本

[英]How to execute sql script before and after each test method

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
}

实际上,当您将@Sql放在class上时, sql脚本将在该 class 中定义的每个测试之前和之后执行,更具体地说,在@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 {
   //
}

如果我的理解是正确的,你想在每个测试方法之前执行一个init脚本将DB放入某个state,然后确保DB回到那个state,对吧?

最简单的解决方案是使用@Transactional 默认情况下,Spring Boot 会自动回滚@Transactional注释测试的测试事务,从而将 DB 重置为原始 state。

但是,应该考虑两个缺点:

  1. @Transactional表示将存在一个跨越测试方法的整个执行的事务,测试的服务方法通常会加入该事务。 因此,不能依赖测试本身来验证生产代码中事务边界的正确性(例如,此“外部”事务可能会覆盖LazyInitializationException
  2. 除非必要,否则持久性上下文不会刷新,这意味着某些问题(例如,违反数据库约束)不会出现。 我倾向于使用最后机会冲洗来解决这个问题,如下所示:
  @After
  public void flushContext() {
    if (TransactionSynchronizationManager.isActualTransactionActive()) {
      entityManager.flush();
    }
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM