Donglecow
Donglecow

Reputation: 497

How to prevent @Rollback in a specific method?

I'm doing tests using Spock in Grails 3. A particular test case is breaking because Grails is speaking to my database in two different sessions in this case. My spec is annotated with @Rollback, to rollback all changes made with each test.

Is there a way to disable @Rollback for this one method, then after the test is complete, manually rollback the changes?

Update

A stripped down example of my test spec is below:

@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){...}
}

The stacktrace for the error is:

<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)

Upvotes: 0

Views: 1126

Answers (3)

Lucas Milotich
Lucas Milotich

Reputation: 398

If you are not interested in rolling back your changes, you don't want to use a transaction... therefore you can skip the transaction in THAT method. You can do it using @NotTransactional.

Upvotes: 0

bassmartin
bassmartin

Reputation: 525

It might be an issue if @Rollback(false) is not working...

As a workaround, the annotation can be put at method level too. So remove the annotation from your test class and put it on your test methods, except the one you don't want to rollback. Then add a cleanup: section in that spec to cleanup the data you created.

Upvotes: 1

Leonard Br&#252;nings
Leonard Br&#252;nings

Reputation: 13242

According to the Javadoc annotating the test with @Rollback(false) should do the trick.

Upvotes: 1

Related Questions