Как устанавливать объекты при функциональном тестировании граалей с помощью Спока

у нас есть пример домена, такого как этот

class User {
    String username
    String password

    def userHelper

    static contraints = {
        username(nullable: false, blank: false)
        password nullable: false, blank: false, validator: {pwd, userInstance ->
            return userInstance.userHelper.validatePassword(pwd)
        }
    }
}

userHelper вводится следующим в моемresources.groovy

beans = {
    userHelper(UserHelper)
}

Когда я тестирую свое приложение из браузера, все работает нормально. Тем не менее, я получаю исключение при попытке написать функциональные тесты для этого.

Ошибка говорит:Cannot invoke method validatePassword() on null object

Так что я'м при условии, чтоuserHelper не устанавливается при запуске моего функционального теста.

Мой тестовый пример выглядит так:

 @TestFor(UserController)
 @Mock([User])

class UserControllerSpecification extends Specification {


    def "save user" () {
        given:
            request.contentType = "application/json"
            request.JSON = """
                            {user:
                                {
                                    username: "somtething"
                                    password: "something"
                                }
                            }
                        """
        when: 
            controller.save()

        then:
            User.count() == 1
    }
}

Обновить

контроллер:

class UserController {
    def userService
    def save() {
        def user = new User(params?.user)
        request.withFormat {
            json {
                if(user.validate())
                  userService.processUser()
                  //do something
                else
                  //do something else
            }
        }
    }
}

Вопросы

Как я могу установитьuserHelper собственность наUser домен до запуска моих тестов?Как я могу запустить свой код вBootstrap.groovy до запуска всех моих функциональных и интеграционных тестов?
 tim_yates18 июн. 2013 г., 17:11
Ты имел ввидуreturn userInstance.userHelper.validatePassword(pwd), или же ?return userHelper.validatePassword(pwd)
 Anthony18 июн. 2013 г., 17:14
я имел в видуreturn userInstance.userHelper.validatePassword(pwd) как я понимаю, второй параметрvalidation проверяется экземпляр класса домена

Ответы на вопрос(2)

Решение Вопроса

Вы пытались использоватьdefineBeans? Поскольку это модульный тест, вы должны явно определить компоненты. Вот как это обычно делается в JUnit

defineBeans{
    userHelper(UserHelper){bean ->
        //in case you have other beans defined inside helper
        bean.autowire = true 
    }
}

Вы можетеdefineBeans в методе настройки, чтобы сделать его доступным для всех тестовых случаев.

@Before
void setup(){
    defineBeans{
        userHelper(UserHelper){bean ->
            //in case you have other beans defined inside helper
            bean.autowire = true 
        }
    }
}   

ОБНОВИТЬ:

Похоже, в случае спока вы можете напрямую ввести боб пружины в модульный тест (тест, который расширяется)Specification

class UserControllerSpecification extends Specification {
    def userHelper //injected here in case of spock

    def "save user" () {
     ................
    }
}
 Luis Muñiz09 мар. 2015 г., 18:39
@dmahapatro ответ, на который вы ссылаетесь, это интеграционный тест, а не юнит-тест! Вот почему они могут ввести боб в тест.
 dmahapatro18 июн. 2013 г., 18:39
@ Энтони Можете ли вы показать контроллер?
 Anthony18 июн. 2013 г., 18:55
пожалуйста, смотрите обновление
 dmahapatro18 июн. 2013 г., 21:03
Можете ли вы иметьdefineBeans вsetup: вместоgiven:
 tanghao29 авг. 2015 г., 10:24
это решение работает для меня. Спасибо за Ваш ответ
 Anthony18 июн. 2013 г., 17:50
к сожалению, это нене работает для меня. Я продолжаю получать ту же ошибку, что validatePassword не может быть вызван для нулевого объекта. Я'Я запускаю мои тестовые случаи, как этоgrails test-app unit:spock Я попытался положить его в функциональную папку, но не повезло (побежал с)grails test-app functional:spock
 dmahapatro18 июн. 2013 г., 17:51
@ Энтони Я думаю, что вы можете напрямую ввести боб в спок модульный тест. Посмотрите на обновление иэтот вопрос также.
 Anthony18 июн. 2013 г., 17:54
это нетоже не работает. :(
 Anthony18 июн. 2013 г., 17:41
Хм, что не сделалт работа. Я добавилdefineBeans вgiven раздел

Попробуйте использовать метакласс.

def setup(){
    User.metaClass.getUserHelper = {new UserHelper()}
}

Вы также можете издеваться над userHelper, если эточто ты хочешь.

def setup(){
    def userHelperMock = Mock(UserHelper)
    userHelperMock.validatePassword(_) >> true
    User.metaClass.getUserHelper = {userHelperMock}
}

Убедитесь, что вы звонитеgetUserHelper() а такжене доступ к частномуuserHelper собственность напрямую. Это может быть хорошей идеей сделать это явно:

password nullable: false, blank: false, validator: {pwd, userInstance ->
    return this.getUserHelper().validatePassword(pwd)
}

@dmahapatro 'ответ на использованиеdefineBeans{...} этоЛучший Кстати, но я думаю, что этоне работает из-заэта ошибка Грааля...

Другое предложение напрямую внедрить компонент в тест будет работать только в расширенном интеграционном тесте.grails.plugin.spock.IntegrationSpec

Ваш ответ на вопрос