почему пустые строки преобразуются в null, передаваемые конструктору объекта домена в Grails 2.4.0?

#unit-testing #grails #groovy #spock #data-conversion

#модульное тестирование #grails #groovy #спок #преобразование данных

Вопрос:

Я новичок в Groovy и Grails. Тест Spock для объекта домена для проверки сохраняемости завершается неудачей из-за преобразования пустой строки в null. Вот код. Объект домена,

 class Todo {

    String name
    Date createdDate
    String priority
    String status

    static constraints = {
        priority blank: true
    }

}
  

Спецификация Spock,

 @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
    }

}
  

Результатом grails test-app является

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

Я обнаружил, что пустая строка '' в строке new Todo(name: 't2', createdDate: new Date(), priority: '', status: 'ok') преобразуется null путем отладки. Через некоторое время в Google я вижу, что в Grails есть функция преобразования пустых строк из веб-формы в null для сохранения, которая может быть отключена конфигурацией grails.databinding.convertEmptyStringsToNull = false в Config.groovy. Но я не думаю, что это относится к Spock UT. Я пробовал, но это работает не так, как я думал.

Мне было интересно, почему пустая строка преобразуется в null в качестве параметра, передаваемого конструктору? Заранее спасибо.

Ответ №1:

Сейчас это немного сложно, но можно заставить работать довольно легко. Следующий тест проходит с Grails 2.3.9…

Класс домена:

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

// ...
  

Модульный тест:

 // 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 == ''
    }
}
  

Ключ применяет ContollerUnitTestMixin к тестовому варианту, хотя на самом деле он не тестирует контроллер. См . https://jira.grails.org/browse/GRAILS-11136 .

Надеюсь, это поможет.

Комментарии:

1. Да, тест проходит после добавления @TestMixin(grails.test.mixin.web.ControllerUnitTestMixin) .

2. для меня это просто решило огромную проблему, хотя grails не слишком впечатлил в этом, так много настроек и странное поведение по умолчанию! в любом случае спасибо!!

3. @soheildb «так много настроек и странное поведение по умолчанию» — Если у вас есть рекомендации по улучшению поведения по умолчанию, пожалуйста, отправьте запрос по адресу github.com/grails/grails-core/issues и мы посмотрим на это.

Ответ №2:

Преобразование пустых строк в null является особенностью привязки данных Grails, поэтому это будет происходить везде, где используется привязка данных. Одним из таких мест является вызов конструктора класса домена с аргументом map . Если вы не хотите, чтобы строка преобразовывалась в null, попробуйте это:

 new Todo().priority = ''