【问题标题】:How to prevent @Rollback in a specific method?如何在特定方法中防止@Rollback?
【发布时间】:2017-09-18 15:01:27
【问题描述】:

我正在使用 Grails 3 中的 Spock 进行测试。一个特定的测试用例正在中断,因为在这种情况下 Grails 在两个不同的会话中与我的数据库对话。我的规范用 @Rollback 注释,以回滚每次测试所做的所有更改。

有没有办法为这个方法禁用@Rollback,然后在测试完成后,手动回滚更改?

更新

我的测试规范的精简示例如下:

@Log4j
@Integration
@Rollback
class PublicationReportBreakingSpec extends Specification {

    @Unroll
    @Rollback
    void "Invalidate #type object and check not in report"(type, status, hits, expect)
    {
        //We want to roll back the changes made to the publication after each pass.

        given: "Find a valid #type publication"
        //Finding publication which is Read (valid, should appear in report)
        final Publication pub = getSinglePub(type, status, hits)

        //Set publication to be Unread (invalid, shouldn't appear in report)
        when: "The #type publication is altered to fail"
        pub.setStatus('Unread')
        pub.save(flush:true, failOnError: true)

        then: "Check the properties match the test case"
        pub.status = 'Unread'

        //Generate report of read publications
        when: "The report is run"
        def resp = PublicationController.reportReadPublications()

        //Make sure report doesn't contain the publication
        then: "Check for expected result #expect"
        checkReportExpectedResult(resp, expect)

        where:
        clause                                            | type       | status   | hits || expect
        "Book is unread"                                  | 'Book'     | 'Read'   | 1200 || 0
        "Article is unread"                               | 'Article'  | 'Read'   | 200  || 0
    }

    //Checks report for expect value
    public void checkReportExpectedResult(resp, expect){...} 

    //Returns single publication based on passed in parameters
    public Publication getSinglePub(type, status){...}
}

错误的堆栈跟踪是:

<testcase name="Testing breaking domain class changes. Book is unread" classname="com.my.project.PublicationReportBreakingSpec" time="118.216">
<failure message="java.lang.IllegalStateException: No transactionManager was specified. Using @Transactional or @Rollback requires a valid configured transaction manager. If you are running in a unit test ensure the test has been properly configured and that you run the test suite not an individual test method." type="java.lang.IllegalStateException">java.lang.IllegalStateException: No transactionManager was specified. Using @Transactional or @Rollback requires a valid configured transaction manager. If you are running in a unit test ensure the test has been properly configured and that you run the test suite not an individual test method.
at grails.transaction.GrailsTransactionTemplate.&lt;init&gt;(GrailsTransactionTemplate.groovy:60)
at com.my.project.PublicationReportBreakingSpec (Removed due to sensitivity)
at com.my.project.PublicationReportBreakingSpec (Removed due to sensitivity)
at groovy.lang.Closure.call(Closure.java:414)
at groovy.lang.Closure.call(Closure.java:430)
at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:96)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:93)
at com.my.project.PublicationReportBreakingSpec.Invalidate #type object and check not in report. Check #clause, publication type #type(PublicationReportBreakingSpec.groovy)

【问题讨论】:

  • 您无法回滚典型的 Geb 测试。您无法控制事务,因为它发生在另一个线程上
  • 好吧,这是有道理的。所以使用@Rollback 是多余的,即使它编译?那么我将如何进行测试?我正在更改域对象并将其保存到数据库中,但看起来好像另一个会话正在运行导致它失败的测试用例,并且它没有获取对对象的保存更改。我正在做.save(flush:true) 我所做的任何更改。
  • 已编辑 OP:抱歉,我刚刚注意到帖子中有错字。我使用 Spock 而不是 Geb 进行测试。
  • 已编辑: 我添加了我的代码和堆栈跟踪的示例。由于敏感,它进行了大量修改,但我相信我已经捕捉到了最重要的部分。

标签: testing grails spock


【解决方案1】:

根据Javadoc@Rollback(false) 注释测试应该可以解决问题。

【讨论】:

  • 我已经尝试过了,使用该特定方法上的注释,我得到一个异常groovy.lang.MissingPropertyException: No such property: value for class: org.grails.transaction.GrailsTransactionAttribute。我也试过 @Rollback(value=false) 导致同样的错误。
  • 我添加了我的代码示例和堆栈跟踪。由于敏感,它进行了大量修改,但我相信我已经捕捉到了最重要的部分。
【解决方案2】:

如果@Rollback(false) 不起作用,这可能是个问题...

作为一种解决方法,注释也可以放在方法级别。因此,从您的测试类中删除注释并将其放在您的测试方法中,除了您不想回滚的方法。然后在该规范中添加 cleanup: 部分以清理您创建的数据。

【讨论】:

    【解决方案3】:

    如果您对回滚更改不感兴趣,您不想使用事务...因此您可以在 THAT 方法中跳过事务。您可以使用@NotTransactional 来完成。

    【讨论】:

      猜你喜欢
      • 2016-03-10
      • 2017-12-22
      • 2011-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-17
      • 2023-04-09
      相关资源
      最近更新 更多