使用JPA和JUnit测试时如何在内存数据库中持续擦除H2

时间:2017-08-08 16:10:27

标签: java spring jpa junit flyway

我的设置是这样的。

连接到使用JPA的内存数据库中的H2,使用Spring配置持久化上下文。数据库设置脚本由Flyway运行,以生成我的表并添加数据。

数据库URL:jdbc:h2:mem:test_data

在我们的JUnit测试中,我们有像这样的setUp和tearDown方法

@Override
protected void setUp() throws Exception {
    this.context = new ClassPathXmlApplicationContext("classpath:/DataContext.xml");
    this.data = this.context.getBean(DataProvider.class);
}   

@Override
protected void  tearDown( ) throws Exception {
    this.context.close();
    this.context = null;
    this.data = null;
}

这里的目的是让每个JUnit测试都能获得它自己的数据库,这似乎有时会起作用,但似乎有时我看起来像是在获得与之前测试相同的数据库。一个例子是我有2个测试:

public void testGetFoos()
{       
    Collection<Foo> foos= data.getFoos();
    assertEquals(NUMBER_OF_FOOS,foos.size());
}

public void testSaveFoos()
{       
    Foo bar = makeDummyFoo();
    data.saveFoo(bar);
    Collection<Foo > foos = data.getFoos();

    assertEquals(NUMBER_OF_FOOS + 1,foos.size());
}

这些方法应该能够以任何顺序运行,并且在运行看似情况的maven构建时,它们能够独立运行而不会相互影响,但是偶尔从eclipse中单独运行JUnit测试类时保存方法将首先运行,然后get方法将运行并得到错误的计数,因为它似乎在mem数据库中与之前的测试方法相同。

所以我的问题是如何使用我的Spring设置在JUnit测试之间杀死内存数据库中的H2?或者什么可能导致它没有正确关闭,如果context.close()方法是正确的方法?

3 个答案:

答案 0 :(得分:1)

我相信使用DbUnit会是一种更好的方法;它的目的正是为了这个目的。看看吧。

祝你好运。

答案 1 :(得分:0)

我建议您使用:

  • @Test对测试方法的注释
  • @Before on setup
  • @After on teardown

您可以将此代码放在@Before中,以确保所有@Test方法都有新的db

Connection connection = DriverManager.getConnection("jdbc:h2:~/test", "sa", "");
Statement stmt = connection .createStatement()
stmt.execute("DROP ALL OBJECTS");
connection.commit();
connection.close();

答案 2 :(得分:0)

您可以使用Spring's @Sql annotation在junit测试的每个测试方法之后设置和拆除数据库,如下所示:

@SqlGroup({
    @Sql(executionPhase = ExecutionPhase.BEFORE_TEST_METHOD, scripts ="classpath:db/data.sql"), 
    @Sql(executionPhase = ExecutionPhase.AFTER_TEST_METHOD, scripts = "classpath:db/clean.sql") 
})
public void test(){
    //test logic
}