4

Environment: Grails 2.3.8

I have a requirement that the user's password could null but can't be blank. So I define the domain like this:

class User{
    ...
    String password
    static constraints = {
        ...
        password nullable:true, blank: false
    }
}

I wrote a unit-test for the constraints:

void "password can be null but blank"() {
    when: "create a new user with password"
    def user = new User(password: password)
    then: "validate the user"
    user.validate() == result
    where:
    password    | result
    "hello"     | true
    ""          | false
    null        | true
}

The "hello" and null cases are fine, but the blank string("") fails: junit.framework.AssertionFailedError: Condition not satisfied:

user.validate() == result
|    |          |  |
|    true       |  false
|               false
app.SecUser : (unsaved)

    at app.UserSpec.password can be null but blank(UserSpec.groovy:24)
  • Is nullable overriding the blank: false?
  • I know that I can use a custom validator to implement the requirement, I'm curious is there any better way?
  • Am I doing something wrong?
Aiden Zhao
  • 564
  • 5
  • 24
  • Which version of grails? Blank is changed to null by data binding in some versions. – Aseem Bansal Jul 15 '15 at 16:53
  • I'm using Grails 2.3.8. As @Jeff Scott Brown 's answer does resolve my problem. I think you are also in the correct direction. So you mean in some other version, my question won't be a problem, right? – Aiden Zhao Jul 15 '15 at 17:04
  • In older versions this was not the case. I don't remember this started when. But yeah I was saying the same thing that Jeff said. – Aseem Bansal Jul 15 '15 at 17:06
  • 1
    The conversion of blank strings to null was introduced in Grails 2.3. See http://grails.github.io/grails-doc/2.3.0/guide/introduction.html#whatsNew23. – Jeff Scott Brown Jul 15 '15 at 17:20

1 Answers1

4

The data binder by default converts blank strings to null. You could configure that to not happen if that is really what you want, or you could fix your test like this:

void "password can be null but blank"() {
    when: "create a new user with password"
    def user = new User()
    user.password = password

    then: "validate the user"
    user.validate() == result

    where:
    password    | result
    "hello"     | true
    ""          | false
    null        | true
}

I hope that helps.

EDIT

If you want to disable the conversion of empty strings to null then you could do something like this:

import grails.test.mixin.TestFor
import grails.test.mixin.TestMixin
import grails.test.mixin.web.ControllerUnitTestMixin
import spock.lang.Specification

@TestFor(User)
@TestMixin(ControllerUnitTestMixin)
class UserSpec extends Specification {

    static doWithConfig(c) {
        c.grails.databinding.convertEmptyStringsToNull = false
    }

    void "password can be null but blank"() {
        when: "create a new user with password"
        def user = new User(password: password)

        then: "validate the user"
        user.validate() == result

        where:
        password | result
        "hello"  | true
        ""       | false
        null     | true
    }
}
Jeff Scott Brown
  • 26,804
  • 2
  • 30
  • 47