使用 JPA 和 JUnit 测试时如何一致地擦除内存数据库中的 H2 [重复]

Posted

技术标签:

【中文标题】使用 JPA 和 JUnit 测试时如何一致地擦除内存数据库中的 H2 [重复]【英文标题】:How to consistently wipe H2 in Memory database when using JPA and JUnit Testing [duplicate] 【发布时间】:2018-01-16 07:30:20 【问题描述】:

我的设置是这样的。

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

数据库网址: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() 方法是正确的方法,可能是什么导致它无法正常关闭?

【问题讨论】:

【参考方案1】:

我相信使用DbUnit 会是更好的方法;它正是为此目的而设计的。看看吧。

祝你好运。

【讨论】:

还有一个更紧密的 Spring 集成 -- springtestdbunit.github.io/spring-test-dbunit【参考方案2】:

我建议你使用:

@Test 对测试方法的注解 @Before 设置 @After 拆解

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

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

【讨论】:

【参考方案3】:

您可以使用 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

【讨论】:

以上是关于使用 JPA 和 JUnit 测试时如何一致地擦除内存数据库中的 H2 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 junit 为 JPA REST API 编写测试用例?

Spring Boot JPA 元模型不能为空!尝试运行 JUnit / 集成测试时

springboot jpa junit测试遇到的问题

从向量中最快擦除元素或更好地使用内存(排序基数)

使用 spring-data-jpa 和 MockMvc 进行 spring boot junit 测试

JPA 和Hibernate annotation区别