我想在每个测试用例之后清理数据库,而不回滚事务。我尝试了DBUnit的DatabaseOperation.DELETE_ALL,但是如果删除违反外键约束,它就不起作用。我知道我可以禁用外键检查,但这也会禁用测试的检查(我想阻止)。我使用的是JUnit 4、JPA 2.0(Eclipselink)和Derby的内存数据库。有什么想法吗谢谢,西奥
2izufjch1#
最简单的方法可能是使用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(); }
字符串
jbose2ul2#
简单:在每次测试之前,启动一个新事务,在测试之后,将其回滚。这将为您提供与之前相同的数据库。确保测试不会创建新的事务;而不是重用现有的。
bbuxkriu3#
我有点困惑,因为DBUnit会在每次测试之前将数据库重新初始化为已知状态。他们还建议最好不要在测试后清理或更改数据。因此,如果您要为下一个测试准备数据库,那么我不会打扰。
kx5bkwkv4#
是的,事务内测试会让你的生活更容易,但是如果事务是你的事情,那么你需要在清理过程中实现补偿事务(在@After中)。这听起来很费力,但如果方法得当,您可能最终会得到一组帮助器方法(在测试中),这些方法可以补偿(清理)在@Before和测试(使用JPA或直接JDBC -任何有意义的方法)期间积累的数据。例如,如果你使用JPA并在测试期间调用实体上的create方法,你可以在所有测试中使用(如果你喜欢的话使用AOP,或者像我们一样使用助手测试方法)一个模式:1.跟踪测试期间创建的所有实体的ID1.将它们按创建的顺序累积起来1.在@After中以相反的顺序重放这些实体的实体删除
@After
@Before
qij5mzcb5#
我的设置非常相似:它是Derby(嵌入式)+ OpenJPA 1.2.2 + DBUnit。下面是我如何处理当前任务的集成测试:在每个@Before方法中,我运行3个脚本:1.删除DB -删除所有表的SQL脚本。
qyswt5oh6#
迟做总比不做好。。我也遇到了同样的问题,并提出了一个非常简单的解决方案:1.在持久化单元配置中将属性“... database.action”设置为值“drop-and-create”1.每次测试后关闭实体管理器和实体管理器工厂persistence.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(); }
型...
s8vozzvw7#
我在每次运行后删除DB文件:
boolean deleted = Files.deleteIfExists(Paths.get("pathToDbFile"));
字符串有点脏,但对我有用。谨致问候
t5fffqht8#
**选项一:**可以在截断表前关闭外键检查,截断表后重新开启。您仍然可以通过这种方式检查测试。**选项2:**H2数据库在最后一次连接关闭时销毁内存数据库。我猜Derby DB支持类似的东西,或者您可以切换到H2。**另请参阅:**我在一个相关问题中使用Hibernate编写了一段代码,用于在每次测试之前截断表:https://stackoverflow.com/a/63747005/471214
lnlaulya9#
不是这个问题的正确答案。但这是Google页面的第一个结果,所以这里是Hibernate用户的答案:
import jakarta.persistence.EntityManager; import org.hibernate.Session; Session session = entityManager.unwrap(Session.class); session.getSessionFactory().getSchemaManager().truncateMappedObjects();
字符串先打电话通知。
9条答案
按热度按时间2izufjch1#
最简单的方法可能是使用nativeQuery jpa方法。
字符串
jbose2ul2#
简单:在每次测试之前,启动一个新事务,在测试之后,将其回滚。这将为您提供与之前相同的数据库。
确保测试不会创建新的事务;而不是重用现有的。
bbuxkriu3#
我有点困惑,因为DBUnit会在每次测试之前将数据库重新初始化为已知状态。
他们还建议最好不要在测试后清理或更改数据。
因此,如果您要为下一个测试准备数据库,那么我不会打扰。
kx5bkwkv4#
是的,事务内测试会让你的生活更容易,但是如果事务是你的事情,那么你需要在清理过程中实现补偿事务(在
@After
中)。这听起来很费力,但如果方法得当,您可能最终会得到一组帮助器方法(在测试中),这些方法可以补偿(清理)在@Before
和测试(使用JPA或直接JDBC -任何有意义的方法)期间积累的数据。例如,如果你使用JPA并在测试期间调用实体上的create方法,你可以在所有测试中使用(如果你喜欢的话使用AOP,或者像我们一样使用助手测试方法)一个模式:
1.跟踪测试期间创建的所有实体的ID
1.将它们按创建的顺序累积起来
1.在
@After
中以相反的顺序重放这些实体的实体删除qij5mzcb5#
我的设置非常相似:它是Derby(嵌入式)+ OpenJPA 1.2.2 + DBUnit。下面是我如何处理当前任务的集成测试:在每个
@Before
方法中,我运行3个脚本:1.删除DB -删除所有表的SQL脚本。
1.用于填充数据的特定于测试的DB单元XML脚本。
我的数据库只有12个表,测试数据集也不是很大,大约有50条记录。每个脚本运行大约需要500毫秒,当添加或修改表时,我手动维护它们。
这种方法可能不推荐用于测试大型数据库,甚至可能不被认为是小型数据库的良好实践;但是,与回滚
@After
方法中的事务相比,它有一个重要的优点:你可以实际检测到在提交时发生了什么(比如持久化分离实体或乐观锁异常)。qyswt5oh6#
迟做总比不做好。。我也遇到了同样的问题,并提出了一个非常简单的解决方案:
1.在持久化单元配置中将属性“... database.action”设置为值“drop-and-create”
1.每次测试后关闭实体管理器和实体管理器工厂
persistence.xml
字符串
单元测试:
型
...
s8vozzvw7#
我在每次运行后删除DB文件:
字符串
有点脏,但对我有用。谨致问候
t5fffqht8#
**选项一:**可以在截断表前关闭外键检查,截断表后重新开启。您仍然可以通过这种方式检查测试。
**选项2:**H2数据库在最后一次连接关闭时销毁内存数据库。我猜Derby DB支持类似的东西,或者您可以切换到H2。
**另请参阅:**我在一个相关问题中使用Hibernate编写了一段代码,用于在每次测试之前截断表:https://stackoverflow.com/a/63747005/471214
lnlaulya9#
不是这个问题的正确答案。但这是Google页面的第一个结果,所以这里是Hibernate用户的答案:
字符串
先打电话通知。