spring – 如何在@Before方法之前执行@Sql

codeday· 2019-09-26
本文来自 codeday ,作者 codeday
我正在尝试结合以下注释:

org.springframework.test.context.jdbc.Sql

org.junit.Before

像下面的代码:

@Test
@Sql(scripts = "dml-parametro.sql")
public void testData(){
    Iterable<Parametro> parametros = parametroService.findAll();
    List<Parametro> parametrosList = Lists.newArrayList(parametros);

    Assert.assertThat(parametrosList.size(), Is.is(1));
}

@Before
public void beforeMethod() {
    JdbcTestUtils.deleteFromTables(jdbcTemplate, "PARAMETRO");
}

方法@Before中的代码在@Sql批注中的脚本“dml-parametro.sql”之后运行.

这样做是对的吗?

为了解决这个问题,我使用@After而不是@Before,但是我想在测试执行之前而不是之后删除表.

我不想使用@SqlConfig.我没有在测试级别上使用transacional scope,所以我需要在每个测试方法中清理我的表.如果每个测试方法都需要清理表,我想在@Before方法中执行此操作.我不想在每个使用@SqlConfig的测试方法中都这样做.我认为@Sql在@Before之前执行的行为是错误的.

最佳答案
默认情况下,任何通过@Sql执行的SQL脚本都将在任何@Before方法之前执行.因此,您遇到的行为是正确的,但您可以通过@Sql中的executionPhase属性更改执行阶段(请参阅下面的示例).

如果要执行多个脚本,也可以通过@Sql执行.

因此,如果您有一个名为clean-parametro.sql的清理脚本从PARAMETRO表中删除,您可以像下面那样注释您的测试方法(而不是在@Before方法中调用JdbcTestUtils.deleteFromTables()).

@Test
@Sql({"dml-parametro.sql", "clean-parametro.sql"})
public void test() { /* ... */ }

当然,如果dml-parametro.sql将值插入PARAMETRO表中,那么在清理脚本中立即删除这些值可能没有意义.

请注意,@ Sql和@SqlConfig为脚本执行提供了多个级别的配置.

例如,如果要在测试之前创建表并在测试之后进行清理,则可以在Java 8上执行以下操作:

@Test
@Sql("create-tables.sql")
@Sql(scripts = "clean-up.sql", executionPhase = AFTER_TEST_METHOD)
public void test() { /* ... */ }

或者使用@SqlGroup作为Java 6或Java 7上的容器:

@Test
@SqlGroup({
    @Sql("create-tables.sql"),
    @Sql(scripts = "clean-up.sql", executionPhase = AFTER_TEST_METHOD)
})
public void test() { /* ... */ }

如果您的测试是@Transactional并且您想要清理已提交的数据库状态,则可以指示Spring在新事务中执行清理SQL脚本,如下所示:

@Test
@Sql("insert-test-data.sql")
@Sql(
  scripts = "clean-up.sql",
  executionPhase = AFTER_TEST_METHOD,
  config = @SqlConfig(transactionMode = ISOLATED)
)
public void test() { /* ... */ }

我希望这能为你澄清一些事情!

干杯,

Sam(Spring TestContext Framework的作者)

笔记:

>从ExecutionPhase静态导入AFTER_TEST_METHOD
> ISOLATED是从TransactionMode静态导入的