繁体   English   中英

如何在spring测试中的@Test方法之前只填充一次数据库?

[英]How to populate database only once before @Test methods in spring test?

我用junit4测试spring服务层的下一个问题是:如何在所有@Test方法之前调用仅填充一次数据库的脚本:我想在所有@Tests之前执行一次:

JdbcTestUtils.executeSqlScript(jdbcTemplate(), new FileSystemResource(
"src/main/resources/sql/mysql/javahelp-insert.sql"), false);

我试图在我的 GenericServiceTest 类(由测试类扩展)上使用 @PostConstruct 。 事实证明,每次@Test 方法之前都会调用@PostConstruct。 有趣的是,甚至在每个@Test 方法之前都会调用 GenericServiceTest 的 @Autowired 注释的方法。

我不想在每个测试类之前填充数据库,而只想在 spring-test 启动时填充一次。

如何在使用 spring 测试框架和 junit4 的所有 @Test 方法之前只执行一次上述方法?

谢谢!

基于 Alfredos 的回答,这是一种无需调用嵌入式数据库的默认脚本即可注入数据库信息的方法。 例如,当您想为您自动构建 DDL 时,这可能很有用 - 至少在测试中。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"/applicationContext.xml"})
public class TestClass {

    @Autowired
    private ApplicationContext ctx;

    private JdbcTemplate template;

    @Autowired
    public void setDataSource(DataSource dataSource) {
       template = new JdbcTemplate(dataSource);
    }

    private static boolean isInitialized = false;

    @Before
    public void runOnce() {
        if (isInitialized) return;
        System.out.println("Initializing database");

        String script = "classpath:script.sql"; 
        Resource resource = ctx.getResource(script);
        JdbcTestUtils.executeSqlScript(template, resource, true);            
        isInitialized = true;
    }
}

这样, runOnce()方法被调用一次,并且只为测试运行调用一次。 如果您使isInitialized成为一个实例字段(非静态),则该方法将在每次测试之前调用。 通过这种方式,您可以在每次测试运行之前删除/重新填充表(如有必要)。

请注意,这仍然是一个相当快速和肮脏的解决方案,处理数据库的明智方法与 Ralph 的答案一致。

使用 Springs 嵌入式数据库支持

<jdbc:embedded-database id="dataSource">
    <jdbc:script location="classpath:myScript.sql"/>
    <jdbc:script location="classpath:otherScript.sql"/>
</jdbc:embedded-database>

或 Springs 初始化数据库支持

<jdbc:initialize-database data-source="dataSource">
    <jdbc:script location="classpath:myScript.sql"/>
    <jdbc:script location="classpath:otherScript.sql"/>
</jdbc:initialize-database>

@见http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jdbc.html#jdbc-embedded-database-support

示例基于 Mike Adlers 示例,但用于 JUnit 5 并使用 Tugdual 提到的 ResourceDatabasePopulator。

为每个测试方法创建一次测试类。 因此,如果您只想填充一次,则需要以某种方式处理它。 这里是用一个静态变量完成的。

@Autowired
private DataSource dataSource;

private static boolean isInitialized;

@BeforeEach // JUnit 5
void initDatabase() {
  if(!isInitialized) { // init only once
    ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
    populator.addScript(new ClassPathResource("/sql/myscript.sql")));
    populator.execute(dataSource);
    isInitialized = true;
  }
}

编辑:一个更好的解决方案。

Junit 5 提供了其他人提到的 @BeforeAll,应该是正确的答案

@Autowired
private DataSource dataSource;

@BeforeAll // JUnit 5
void initDatabase() {
  ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
  populator.addScript(new ClassPathResource("/sql/myscript.sql")));
  populator.execute(dataSource);
}

如果您是 Spring Boot,您可以通过以下方式提及要在测试前启动的多个脚本

spring.datasource.data=classpath:accounts.sql, classpath:books.sql, classpath:reviews.sql

您可以使用 JUnit 5 的 @BeforeAll 注释

暂无
暂无

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

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