简体   繁体   中英

Calling entity.delete(flush: true) in a Spock test does not flush, nor does using withTransaction, one has to run both separately

I have a Grails 5.2.5 app with a Spock 2.0 test. In it, I try to delete an entity like so:

def "experiment"() {
    given:
        MyEntity entity = new MyEntity().save(failOnError: true)).save(failOnError: true)
    when:
        entity.delete()
    then:
        MyEntity.count() == 0 // fails
}

It fails. The saved entity stays there after the deletion attempt. If I replace entity.delete() with any of the three options below, it still fails.

        MyEntity.withSession {
            entity.delete(flush: true, failOnError: true)
        }
// OR
        MyEntity.withTransaction {
            entity.delete(flush: true, failOnError: true)
        }
// OR
        entity.delete(flush: true, failOnError: true)

Or if I remove failOnError:true .

I am basically currently unable to delete stuff from DB during a spock test and I used to be able to do that in Grails 2.x, so not sure how to migrate those tests.

Edit:

I had managed to delete an entity like so, but it makes no sense to me, why these should work and the aboves not:

def "experiment"() {
    given:
        MyEntity entity = new MyEntity().save(failOnError: true)).save(failOnError: true)
    when:
        entity.delete(flush: true) // here flush is necessary
        MyEntity.withTransaction {
            entity.delete()
        }
    then:
        MyEntity.count() == 0 // passes
}

and to my utter amazement this works as well even without the flush, whereas above the flush is necessary:

def "experiment"() {
    given:
        MyEntity entity = new MyEntity().save(failOnError: true)).save(failOnError: true)
    when:
        MyEntity.withTransaction {
            entity.delete()
        }
        entity.delete() // here flush is not necessary
    then:
        MyEntity.count() == 0 // passes
}

What source ry is this..

Alright, the problem was I only flushed the delete, not the save operation. I thought I didn't have to since the saved entity was found during .count() operation.

Hibernate flushMode has COMMIT as default value instead of the AUTO from the past. Documentation has an error on this, I posted a PR to fix the doc, the change was mentioned only in release notes, but doc wasn't updated .

Since that has changed, now that I want to save entities and delete them in tests, I need to flush both operations.

So this works now okay:

def "experiment"() {
    given:
        MyEntity entity = new MyEntity().save(failOnError: true, flush: true) // flush was added here that wasn't here before
    when:
        entity.delete(flush: true) // flush needs to be here as well.
    then:
        MyEntity.count() == 0 // works now
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM