15

我想在每个测试用例之后清理数据库而不回滚事务。我已经尝试过 DBUnit 的DatabaseOperation.DELETE_ALL,但是如果删除违反了外键约束,它就不起作用。我知道我可以禁用外键检查,但这也会禁用测试检查(我想阻止)。

我正在使用 JUnit 4、JPA 2.0 (Eclipselink) 和 Derby 的内存数据库。有任何想法吗?

谢谢,西奥

4

8 回答 8

18

最简单的方法可能是使用 nativeQuery jpa 方法。

@After
public void cleanup() {
    EntityManager em = entityManagerFactory.createEntityManager();
    em.getTransaction().begin();
    em.createNativeQuery("truncate table person").executeUpdate();
    em.createNativeQuery("truncate table preferences").executeUpdate();
    em.getTransaction().commit();
}
于 2013-04-22T19:12:59.577 回答
5

简单:在每次测试之前,启动一个新事务,在测试之后,将其回滚。这将为您提供与以前相同的数据库。

确保测试不会创建新事务;而是重用现有的。

于 2011-07-20T14:58:01.843 回答
2

我有点困惑,因为 DBUnit 会在每次测试之前将数据库重新初始化为已知状态。

他们还建议作为最佳实践,不要在测试后清理或以其他方式更改数据。

因此,如果您正在清理您为下一次测试准备数据库,我不会打扰。

于 2010-10-13T16:32:30.437 回答
2

是的,事务中测试会让你的生活更轻松,但如果事务是你的事,那么你需要在清理期间实现补偿事务(in @After)。这听起来很费力,但如果处理得当,您最终可能会得到一组辅助方法(在测试中),以补偿(清理)在@Before测试期间积累的数据(使用 JPA 或直接 JDBC - 任何有意义的)。

例如,如果您在测试期间使用 JPA 并在实体上调用 create 方法,您可以使用(如果您喜欢使用 AOP,或者只是像我们这样的辅助测试方法)跨所有测试的模式来:

  1. 跟踪测试期间创建的所有实体的 ID
  2. 按创建顺序累积它们
  3. 以相反的顺序重播这些实体的实体删除@After
于 2010-10-13T20:56:37.170 回答
0

我的设置非常相似:它是 Derby(嵌入式)+ OpenJPA 1.2.2 + DBUnit。以下是我为当前任务处理集成测试的方式:在每种@Before方法中,我运行 3 个脚本:

  1. Drop DB — 删除所有表的 SQL 脚本。
  2. Create DB — 一个重新创建它们的 SQL 脚本。
  3. 用于填充数据的特定于测试的 DB 单元 XML 脚本。

我的数据库只有 12 个表,测试数据集也不是很大——大约 50 条记录。每个脚本运行大约需要 500 毫秒,我在添加或修改表时手动维护它们。

这种方法可能不推荐用于测试大型数据库,对于小型数据库,它甚至不能被认为是好的做法;但是,与回滚@After方法中的事务相比,它有一个重要优势:您实际上可以检测到提​​交时发生的情况(例如持久化分离实体或乐观锁异常)。

于 2011-07-20T14:29:51.967 回答
0

迟到总比永远好……我也遇到了同样的问题,并提出了一个非常简单的解决方案:

  1. 在您的持久性单元配置中将属性“ ...database.action ”设置为值“ drop-and-create ”
  2. 每次测试后关闭实体管理器和实体管理器工厂

持久性.xml

    <persistence-unit name="Mapping4" transaction-type="RESOURCE_LOCAL" >
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>...</class>
    <class>...</class>

    <properties>
        ...
        <property name="javax.persistence.schema-generation.database.action" value="drop-and-create" />
        ...
    </properties>
</persistence-unit>

单元测试:

...
@Before
public void setup() {
    factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
    entityManager = factory.createEntityManager();
}


@After
public void tearDown() {
    entityManager.clear();
    entityManager.close();
    factory.close();
}

...

于 2018-06-12T13:15:34.353 回答
0

每次运行后我都会删除数据库文件:

boolean deleted = Files.deleteIfExists(Paths.get("pathToDbFile"));

有点脏,但对我有用。问候

于 2020-04-06T13:48:35.897 回答
0

选项 1:您可以在截断表之前禁用外键检查,并在截断后再次启用它们。您仍然可以通过这种方式检查测试。

选项 2: H2 数据库在最后一个连接关闭时销毁内存数据库。我猜 Derby DB 支持类似的东西,或者你可以切换到 H2。

另请参阅:我在相关问题中使用 Hibernate 在每次测试之前编写了截断表的代码:https ://stackoverflow.com/a/63747005/471214

于 2020-09-04T19:28:17.790 回答