我想在每个测试用例之后清理数据库而不回滚事务。我已经尝试过 DBUnit 的DatabaseOperation.DELETE_ALL,但是如果删除违反了外键约束,它就不起作用。我知道我可以禁用外键检查,但这也会禁用测试检查(我想阻止)。
我正在使用 JUnit 4、JPA 2.0 (Eclipselink) 和 Derby 的内存数据库。有任何想法吗?
谢谢,西奥
我想在每个测试用例之后清理数据库而不回滚事务。我已经尝试过 DBUnit 的DatabaseOperation.DELETE_ALL,但是如果删除违反了外键约束,它就不起作用。我知道我可以禁用外键检查,但这也会禁用测试检查(我想阻止)。
我正在使用 JUnit 4、JPA 2.0 (Eclipselink) 和 Derby 的内存数据库。有任何想法吗?
谢谢,西奥
最简单的方法可能是使用 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();
}
简单:在每次测试之前,启动一个新事务,在测试之后,将其回滚。这将为您提供与以前相同的数据库。
确保测试不会创建新事务;而是重用现有的。
我有点困惑,因为 DBUnit 会在每次测试之前将数据库重新初始化为已知状态。
他们还建议作为最佳实践,不要在测试后清理或以其他方式更改数据。
因此,如果您正在清理您为下一次测试准备数据库,我不会打扰。
是的,事务中测试会让你的生活更轻松,但如果事务是你的事,那么你需要在清理期间实现补偿事务(in @After
)。这听起来很费力,但如果处理得当,您最终可能会得到一组辅助方法(在测试中),以补偿(清理)在@Before
测试期间积累的数据(使用 JPA 或直接 JDBC - 任何有意义的)。
例如,如果您在测试期间使用 JPA 并在实体上调用 create 方法,您可以使用(如果您喜欢使用 AOP,或者只是像我们这样的辅助测试方法)跨所有测试的模式来:
@After
我的设置非常相似:它是 Derby(嵌入式)+ OpenJPA 1.2.2 + DBUnit。以下是我为当前任务处理集成测试的方式:在每种@Before
方法中,我运行 3 个脚本:
我的数据库只有 12 个表,测试数据集也不是很大——大约 50 条记录。每个脚本运行大约需要 500 毫秒,我在添加或修改表时手动维护它们。
这种方法可能不推荐用于测试大型数据库,对于小型数据库,它甚至不能被认为是好的做法;但是,与回滚@After
方法中的事务相比,它有一个重要优势:您实际上可以检测到提交时发生的情况(例如持久化分离实体或乐观锁异常)。
迟到总比永远好……我也遇到了同样的问题,并提出了一个非常简单的解决方案:
持久性.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();
}
...
每次运行后我都会删除数据库文件:
boolean deleted = Files.deleteIfExists(Paths.get("pathToDbFile"));
有点脏,但对我有用。问候
选项 1:您可以在截断表之前禁用外键检查,并在截断后再次启用它们。您仍然可以通过这种方式检查测试。
选项 2: H2 数据库在最后一个连接关闭时销毁内存数据库。我猜 Derby DB 支持类似的东西,或者你可以切换到 H2。
另请参阅:我在相关问题中使用 Hibernate 在每次测试之前编写了截断表的代码:https ://stackoverflow.com/a/63747005/471214