Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why are empty strings converted to null passing to the constructor of the domain object in Grails 2.4.0?

I'm new to Groovy and Grails. The Spock test for the domain object to test persist fails due to the empty string being converted to null. Here is the code. The domain object,

class Todo {

    String name
    Date createdDate
    String priority
    String status

    static constraints = {
        priority blank: true
    }

}

The Spock specification,

@TestFor(Todo)
class TodoSpec extends Specification {

    void "test persist"() {
        when:
        new Todo(name: 't1', createdDate: new Date(), priority: "1", status: 'ok').save()
        new Todo(name: 't2', createdDate: new Date(), priority: '', status: 'ok').save()

        then:
        Todo.list().size() == 2
    }

}

The result of grails test-app is

Todo.list().size() == 2
     |      |      |
     |      1      false
     [collab.todo.Todo : 1]
        at collab.todo.TodoSpec.test persist(TodoSpec.groovy:18)

I found the empty string '' in the line new Todo(name: 't2', createdDate: new Date(), priority: '', status: 'ok') is converted to null by debugging. After google a while, I see there is a feature in Grails converting the empty strings from the web form to null to persist, which can be disabled by a configuration grails.databinding.convertEmptyStringsToNull = false in the Config.groovy. But I don't think this is the case for Spock UT. I've tried but it doesn't work as I thought.

I was wondering why the empty string is converted to null as a parameter passing to the constructor? Thanks in advance.

like image 930
user3737977 Avatar asked Jun 13 '14 14:06

user3737977


1 Answers

It is a little hinky right now, but can be made to work pretty easily. The following test passes with Grails 2.3.9...

A domain class:

// grails-app/domain/com/demo/Person.groovy
package com.demo

class Person {
    String title
}

Config.groovy:

// grails-app/conf/Config.groovy
grails.databinding.convertEmptyStringsToNull = false

// ...

A unit test:

// test/unit/com/demo/PersonSpec.groovy
package com.demo

import grails.test.mixin.TestFor
import spock.lang.Specification

@TestFor(Person)
@TestMixin(grails.test.mixin.web.ControllerUnitTestMixin)
class PersonSpec extends Specification {

    void "test empty string conversion"() {
        when:
        def p = new Person(title: '')

        then:
        p.title == ''
    }
}

The key is applying the ContollerUnitTestMixin to the test case, even though it isn't really testing a controller. See https://jira.grails.org/browse/GRAILS-11136.

I hope that helps.

like image 139
Jeff Scott Brown Avatar answered Nov 15 '22 03:11

Jeff Scott Brown