带@Sql的@SpringBootTest:脚本执行和上下文初始化的顺序

时间:2017-05-11 11:42:05

标签: java spring-boot junit spring-boot-test

我有在内存数据库中执行的集成测试。每个测试的签名看起来或多或少都是这样的:

@RunWith(SpringRunner.class)
@SpringBootTest
@Sql("/clean-data-in-all-tables.sql")
public class SomeTest { 
    @Test
    public void shouldDoSomehting() {}
}

在测试上下文初始化期间,数据库模式由Hibernate重新创建:

spring:
  jpa:
    hibernate:
      ddl-auto: create-drop

我希望在初始化上下文之后和生成数据库模式之后执行sql脚本。但是,在某些情况下clean-data-in-all-tables.sql在模式生成之前执行,并且失败,因为它需要尚未创建的表。

我按照我解释的方式编写了500多个测试,并且它们都运行良好,直到我添加了更多类似的测试。

当我通过Gradle或IntelliJ一起执行测试时,测试失败。 请注意,失败的测试不是最近添加的测试。这是与我添加的测试完全无关的旧测试。同样奇怪的是,如果我通过IntelliJ逐一运行,那么失败的测试工作正常。

它看起来像是一个弹簧启动的错误,但我仍然试图找到解决方法。与此同时,我尝试了许多方法来解决这个问题,但是没有一个是有用的。

请分享您对我的代码可能有用和可能出现的问题的想法。

更新 找到了解决方法:将spring.jpa.hibernate.ddl-autocreate-drop更改为create可以解决问题。

但问题仍然是开放这种奇怪行为的原因是什么?

1 个答案:

答案 0 :(得分:2)

一种可能的解决方案(我不确定您是否愿意使用DBUnit)可以是:

1)创建抽象存储库集成测试:

@TestExecutionListeners({DbUnitTestExecutionListener.class})
@SpringApplicationConfiguration(classes = Application.class)
@DirtiesContext
public abstract class AbstractRepositoryIT extends AbstractTransactionalJUnit4SpringContextTests {
}

2)创建“真正的”集成测试:

@DatabaseSetup(SomeEntityRepositoryIT.DATASET)
@DatabaseTearDown(type = DatabaseOperation.DELETE_ALL, value = {"dataset.xml})
public class SomeEntityRepositoryIT extends AbstractRepositoryIT {
...
}

在文件dataset.xml中,您可以为测试等设置初始状态...... {{3}}