JUnit 测试总是回滚事务
Posted
技术标签:
【中文标题】JUnit 测试总是回滚事务【英文标题】:JUnit tests always rollback the transactions 【发布时间】:2012-03-22 06:21:12 【问题描述】:我正在对应用程序 DAO 运行一个简单的 JUnit 测试。问题是我总是得到:
javax.persistence.RollbackException: Transaction marked as rollbackOnly
JUnit 测试是:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:com/my/app/context.xml"
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
@Transactional
public class PerformanceTest
@Test
@Transactional(propagation= Propagation.REQUIRES_NEW)
@Rollback(false)
public void testMsisdnCreationPerformance()
// Create a JPA entity
// Persist JPA entity
如您所见,我明确声明不回滚此方法。
Spring JUnit 支持是否总是将回滚设置为 true?
【问题讨论】:
你从哪里得到异常?你可以发布堆栈跟踪吗? 【参考方案1】:它应该像你期望的那样工作,但可能是你在你的测试类中打开了另一个事务,或者你在某个地方有其他功能/或错误。
顺便说一句,这个注释应该足够了:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:com/my/app/context.xml"
@Transactional
public class PerformanceTest
@Test
@Rollback(false)
public void testMsisdnCreationPerformance()
// Create a JPA entity
// Persist JPA entity
@见Spring Reference Chapter 9.3.5.4 Transaction management
【讨论】:
【参考方案2】:只需添加注解 Rollback 并将标志设置为 false。
@Test
@Rollback(false)
【讨论】:
【参考方案3】:想要一个更改您的数据库并保留修改的测试是很奇怪的。 测试应该是正交的:没有测试依赖于另一个。 此外,测试应该独立于测试顺序,甚至idempotent。
因此,要么您想在 setUp()
方法中更改数据库并回滚 tearDown()
方法中的更改,要么您想设置一个测试数据库,其中包含一些用于测试的好值。
也许我在这里遗漏了一些东西,但通常你不应该这样。
【讨论】:
但这不是问题。 我有一个很好的理由不回滚 junit 测试。因此,“正确答案”并不是您不应该这样做。正确的答案是可以解释如何的人。 能否请您添加一些关于如何在设置方法中添加一些数据的评论,仍然可以在被测代码中的任何地方看到它然后回滚它? 不回答问题。有时您将 junit 功能用于各种目的。如果有人问我希望能够在 junit 中提交 - 提供如何做到这一点的答案,然后说如果它是真正的 junit(可重复测试),这可能不是最佳实践。 @SeanPatrickFloyd 提示在 REQUIRED_NEW 上,这表明他显然正在尝试在执行集成测试之前设置特定的数据库状态。因此,它需要在测试的行为部分之前持久化。所以是的,我认为我们应该坚持回答这个问题。【参考方案4】:来自官方文档:
默认情况下,测试事务会自动回滚 完成测试;然而,事务提交和回滚 可以通过@Commit 和@Rollback 以声明方式配置行为 注释
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html#integration-testing-annotations
@Commit 表示该事务为一个事务性测试方法 应在测试方法完成后提交。 @Commit 可以 用作@Rollback(false) 的直接替代品,以便更多 明确传达代码的意图。
【讨论】:
令我非常困惑的是,即使异常一直冒泡,测试也会提交 txn,通常情况下(@Transactional 在业务类上而不是在测试方法上)会触发txn 回滚。 仅适用于已检查的异常。未选中将自动回滚。 ***.com/questions/3701376/…【参考方案5】:I use Junit5, both commit and rollback(false) works with me.
@ExtendWith(SpringExtension.class)
@SpringBootTest
@Transactional
public class MyIntegrationTest
@Test
@DisplayName("Spring Boot Will Rollback Data, " +
"Can Disable it By Add @Commit Or @Rollback(false) Annotation")
//@Commit
//@Rollback(false)
public void test() throws Exception
//your test codes here...
【讨论】:
【参考方案6】:我同意拉尔夫的回答。
Propagation.REQUIRES_NEW 创建一个新事务,这可能与运行测试的主要事务路由不匹配。
根据我的简单经验,注释 @Transactional 将正常工作以定义每个测试应在其中运行的事务上下文,将特定的当前回滚子句委托给该上下文(如 Ralph 所示)。
Ralph 的答案很有用,同时 Snicolas 的答案涉及管理测试上下文的特定案例。 幂等性是集成和自动测试的基础,但应该以不同的方式来实现它们。 问题是,你有什么样的方法?这些方法有什么行为?
[...]
@Transactional
public class Test
@Test
@Rollback(false)
public void test()
[...]
是简单的,问题连贯的方式:)
【讨论】:
【参考方案7】:在您的测试类级别添加@Rollback
在您的测试方法中添加@Transactional(value = "your_ManagerName",rollbackFor = Exception.class)
【讨论】:
以上是关于JUnit 测试总是回滚事务的主要内容,如果未能解决你的问题,请参考以下文章
事务回滚在 JUnit5 的 @Nested 类的测试用例中不起作用