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

时间:2013-07-06 18:39:24

标签: java mysql spring 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方法之前调用注释了@Autowired of GenericServiceTest的方法。

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

如何在使用spring test framework和junit4的所有@Test方法之前只执行一次上面的方法?

谢谢!

5 个答案:

答案 0 :(得分:12)

基于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的答案一致。

答案 1 :(得分:11)

使用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>

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

答案 2 :(得分:1)

如果您是春季启动,您可以提及多个脚本,以便在测试之前通过

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

答案 3 :(得分:0)

该示例基于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;
  }
}

答案 4 :(得分:0)

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