【问题标题】:Grails: Transactions in Integration TestsGrails:集成测试中的事务
【发布时间】:2012-03-26 03:29:32
【问题描述】:

我有一个非常简单的设置 - 一个调用服务方法的控制器。在此服务中,我将一个对象保存到数据库,并将 JMS 消息发送到队列 - 一旦保存 - 使用注入的 JMSTemplate。该服务默认启用事务。

手动测试时——ActiveMQ 服务器关闭——抛出异常并回滚事务——最终结果是对象也不会保存到数据库中。都很好。

但是,当我通过集成测试(ActiveMQ 仍处于关闭状态)运行此程序时,我必须在调用控制器后使用计数查询检查对象是否未保存在数据库中的断言,说计数为 1 失败。我通过在测试开始时添加另一个断言以确保计数为 0 来确认测试开始时数据库没有任何这些对象。

这是预期的行为(可能是由于集成测试环境中事务的性质)还是我可能做错了什么?该异常仍在抛出,因为 JMS 服务器已关闭 - 这是一个 RuntimeException。

Grails integration tests and transactions 给人的印象是这是意料之中的——在这种情况下,关于如何在集成测试中测试事务行为的最佳实践有什么建议吗?

【问题讨论】:

  • 如果我没记错的话,事务直到测试完成后才会回滚。因此,当您执行断言时,看起来数据已保存到数据库中,因为事务尚未回滚。
  • 是的,情况确实如此,因为似乎在测试和控制器中都使用了相同的事务。想知道在这样的情况下是否有一个标准范式可以使用。我不想仅仅为了测试而更改控制器代码以使其需要新事务。
  • 这篇博文 - fepede.net/blog/?p=27 展示了如何使测试成为非事务性的,这将导致控制器和服务拥有自己的事务(不使用测试的事务)。缺点是如果没有抛出异常,事务就会提交,你必须自己清理。

标签: grails integration-testing


【解决方案1】:

不知道为什么每个人都发表评论而不是回答,因为 cmets 确实公开了答案。我会跳进去尝试抢答题!

是的,在 Spock 测试中,整个测试,包括 whens、thens、givens 等都在同一个事务中运行。因此,在完成测试之前,您不会看到您希望的回滚。

您可以通过在测试类的顶部添加“static transactional = false”来将测试设置为非事务性。当然,后果是您需要在运行测试后清理数据库(如果数据库卫生对您很重要)。这里的一个大问题是 Grails IntegrationSpec 类中有一个错误,当您尝试将 transactional 设置为 false 时,该错误就会爆炸。这个 SO 有解决这个问题的方法:

Grails 2.3 IntegrationSpec cannot be transactional false

基本上,将 grails.test.spock.IntegrationSpec 的所有代码复制到您自己的类中,并用尊重测试事务性质的版本替换一些方法。

【讨论】:

    猜你喜欢
    • 2011-05-07
    • 1970-01-01
    • 2014-09-27
    • 1970-01-01
    • 1970-01-01
    • 2013-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多