Consider the following code:
class User {
static constraints = {
email email: true, unique: true
token nullable: true
}
String email
String password
String token
}
@TestFor(User)
@TestMixin(DomainClassUnitTestMixin)
class UserSpec extends Specification {
def "email should be unique"() {
when: "twice same email"
def user = new User(email: "[email protected]", password: "test")
def user2 = new User(email: "[email protected]", password: "test")
then: "saving should fail"
user.save()
!user2.save(failOnError: false)
}
}
With the following configuration (part of it), application.yml:
grails:
gorm:
failOnError: true
autoFlush: true
Why is user2.save(failOnError: false)
not returning false
due to it not being saved into the database?
Output of running: grails test-app *UserSpec
:
businesssoftware.UserSpec > email should be unique FAILED org.spockframework.runtime.ConditionNotSatisfiedError at UserSpec.groovy:40
When I replace user.save()
with user.save(flush: true)
it does work.
However the documentation at https://grails.github.io/grails-doc/latest/guide/conf.html, Section 4.1.3 claims that:
grails.gorm.autoFlush - If set to true, causes the merge, save and delete methods to flush the session, replacing the need to explicitly flush using save(flush: true).
For reference this is the output of grails --version
:
| Grails Version: 3.0.2
| Groovy Version: 2.4.3
| JVM Version: 1.8.0_40
And that's exactly what I am doing, what am I missing here?
I think the autoFlush documentation is misleading.
Take a look at the save() methods and doSave() of GormInstanceApi. Toward the end of doSave() you'll see the session is only flushed when the flush parameter is true:
There's nothing in the code suggesting that the flush parameter can come from any other place than what's passed to save().
I could not find the code to prove it, but I think autoFlush comes into play when the Hibernate session is closed, such as when a controller or service method exists/returns.
Also, the GORM implementation used for Spock and JUnit is not the real GORM, so it may not even use the autoFlush configuration.
I'm going to go on a limb here. I haven't tried this, but you may be able to flush the session manually.
simpleDataStore comes from DomainClassUnitTestMixin.