使用服务和 DAO 测试事务传播

Posted

技术标签:

【中文标题】使用服务和 DAO 测试事务传播【英文标题】:test transaction propagation with service and DAO 【发布时间】:2015-06-01 02:19:57 【问题描述】:

我有一个服务类的服务方法,它是一个 Spring bean,看起来像

@Transactional
public void doThis() 
    dao.d1();
    dao.d2();

在我的 DAO 类中,它扩展了 Spring 的 NamedParameterJdbcDaoSupport。我把它设置为

@Transactional(propagation = Propagation.MANDATORY)
public void d1()...

@Transactional(propagation = Propagation.MANDATORY)
public void d2()...

配置看起来像

<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />

现在我的问题是,如何在 Spring 上下文中对其进行集成测试?我已经使用 AbstractTransactionalJUnit4SpringContextTests 和嵌入式数据库测试了我的 DAO。我现在将如何测试服务链和 DAO,如果 dao 抛出 RuntimeException,我可以看到整个事务被回滚?

希望我解释清楚。欢迎任何提示/建议

【问题讨论】:

【参考方案1】:

如果不检测您的代码来测试这种事务性案例,可能很难将其转变为简单的可重复 JUnit 测试。

使用 dao 中的一些额外代码,您可以让 d2 方法寻找一些东西来强制它抛出测试 RuntimeException。也许可以使用 ThreadLocal 标志来指示您希望代码失败。

或者,您可以让 d2() 每次都失败,直到您对正确应用事务语义感到满意为止。

【讨论】:

感谢您的评论,马克。我想知道我是否可以使用一个DAO模拟,首先在d1方法中抛出异常,然后测试服务层调用者中的事务是否回滚;然后更改mock,让它在d2中抛出异常,并查看事务是否回滚。那是我的理想主义案例 我喜欢使用 DAO 模拟 - 但我不确定您的第一个测试将验证什么。如果 d1() 中止,则 d2() 永远不会被调用,对吗?让 d2() 中止应该回滚 d1() 的更改。我的另一个想法是关于你将在哪里验证回滚。您的对象状态可能不足以检查 - 也许更好地验证底层数据存储? 是的,马克。我想测试 d2 是否失败,d1 是否回滚,我正在检查是否使用存储在嵌入式数据存储中的数据【参考方案2】:

我实际上只是使用 AbstractTransactionalJUnit4SpringContextTests 和嵌入式数据库对其进行了测试,因为我将测试我的 DAO。只需在故事中添加服务层和一个 DAO 存根,该存根会在下游触发的方法中抛出 RuntimeException。它工作得很好。事务回滚验证完毕

【讨论】:

以上是关于使用服务和 DAO 测试事务传播的主要内容,如果未能解决你的问题,请参考以下文章

解决使用JUNIT测试DAO事务一直ROLL BACK问题

Spring 事务传播行为

如何使用springboot编写rest控制器、服务和dao层的junit测试用例?

正确实现一个 dao 类来管理事务

使用 DAO 和 Web 服务的数据库插入方法的 Junit 测试用例

spring事物中的传播及隔离