Внедрение зависимостей в тест спецификации Grails Spock

Мне нужно внедрить зависимости в объекты моего домена в моих тестах.

Эти тесты размещаются в каталоге test/integration и простираются от spock.lang.Specification.

Как я могу этого добиться?

Примечание. Я видел этот пост Как внедрить бобы Spring в тест spock., но это не связано с Grails.

Редактировать:

Зависимость, которую я хочу внедрить, это springSecurityService в моем подклассе SecUser под названием Player. Не работает метод encodePassword(), который вызывается в методе beforeInsert().

Я могу имитировать этот метод encodePassword() в некоторых тестах, но когда я хочу протестировать метод save() моего контроллера, я не могу имитировать создаваемый Player, потому что все это происходит внутри метода контроллеров.

После изменения на расширение IntegrationSpec это мой тестовый код:

package intertigre.test.domain
import intertigre.domain.Fecha;
import intertigre.test.util.DomainFactoryTestService
import grails.plugin.spock.IntegrationSpec
import grails.test.mixin.TestFor

    @TestFor(Fecha)
    class FechaSpec extends IntegrationSpec{

    DomainFactoryTestService domainFactoryTestService = new DomainFactoryTestService()

    def 'test'(){
        given:
            def fecha = new Fecha()
        when:
            fecha.save()
        then:
            Fecha.get(1) == fecha
    }

}

Я получаю это исключение при запуске grails test-app :spock:

java.lang.NullPointerException: Cannot get property 'mainContext' on null object
    at grails.plugin.spock.IntegrationSpec.$spock_initializeSharedFields(IntegrationSpec.groovy)

И это, когда я запускаю тест в одиночку:

| Failure:  intertigre.test.domain.FechaSpec
|  java.lang.NullPointerException: Cannot get property 'autowireCapableBeanFactory' on null object
    at grails.plugin.spock.IntegrationSpec.setupSpec(IntegrationSpec.groovy:47)
| Failure:  intertigre.test.domain.FechaSpec
|  java.lang.NullPointerException: Cannot invoke method isActive() on null object
    at grails.test.mixin.support.GrailsUnitTestMixin.shutdownApplicationContext(GrailsUnitTestMixin.groovy:232)
    at org.spockframework.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:176)
    at org.spockframework.runtime.extension.builtin.JUnitFixtureMethodsExtension$FixtureType$FixtureMethodInterceptor.intercept(JUnitFixtureMethodsExtension.java:145)
    at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:84)
    at org.spockframework.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:176)

person Tomas Romero    schedule 13.08.2012    source источник
comment
@AutoWired, может быть? Ваше приложение Grails работает, когда вы запускаете тесты?   -  person Will    schedule 13.08.2012
comment
Может быть, лучше издеваться над этими зависимостями? Какие зависимости не внедряются? Напишите пример кода, чтобы показать проблему.   -  person Tomasz Kalkosiński    schedule 13.08.2012
comment
Я никогда не пробовал использовать @Autowired в Grails, попробую. Я не запускаю приложение, когда запускаю тесты.   -  person Tomas Romero    schedule 13.08.2012
comment
Я обновил свой вопрос, добавив больше данных, позже добавлю код   -  person Tomas Romero    schedule 13.08.2012


Ответы (2)


Попробуйте объявить springSecurityService в тесте, как в контроллере. Grails должен делать всю работу за вас :)

Для интеграционного теста вы делаете что-то вроде этого:

package intertigre.test.domain
import intertigre.domain.Fecha;
import intertigre.test.util.DomainFactoryTestService
import grails.plugin.spock.IntegrationSpec

class DomainFactoryTestServiceSpec extends IntegrationSpec{

def domainFactoryTestService // you dont need to create a new instance, it's injected by spring

def 'test'(){
     given:
         // ...
     when:
         // ...
     then:
         // ....
 }

Если вам нужно протестировать определенный объект домена (как ваш класс Fecha), вам, вероятно, понадобится модульный тест, что-то вроде этого:

package intertigre.test.domain
import intertigre.domain.Fecha
import intertigre.test.util.DomainFactoryTestService
import grails.test.mixin.TestFor
import grails.test.mixin.Mock
import spock.lang.Specification

@TestFor(Fecha)
@Mock([OtherObject1, OtherObject2])
class FechaSpec extends Specification {

def domainFactoryTestService // same thing here, if you need the service

def 'test'() {
     given:
         def fecha = new Fecha()
     and:
         def oo1 = new OtherObject1()
     when:
         // ...
     then:
         // ....
 }

Вы также можете использовать модульный тест для тестирования сервисов, это зависит от того, что вы собираетесь тестировать (класс — сервис — или «ситуация» — способ использования сервиса).

Пс. Конечно, этот код здесь не тестировался и может содержать опечатки. :) Но я надеюсь, вы поняли мою мысль о том, как тестировать.

person lucke84    schedule 14.08.2012
comment
На самом деле я расширяю спецификацию вместо IntegrationSpec. Когда я пытаюсь изменить для расширения IntegrationSpec, я получаю следующее исключение при выполнении тестов: java.lang.NullPointerException: Не удается получить свойство mainContext для нулевого объекта в grails.plugin.spock.IntegrationSpec.$spock_initializeSharedFields(IntegrationSpec.groovy) - person Tomas Romero; 16.08.2012
comment
Вы должны расширить IntegrationSpec при выполнении интеграционного теста code.google.com /p/grails-spock-examples/wiki/ Есть ли место, где вы объявляете этот нулевой mainContext? Какую версию плагина spock вы сейчас используете? Можете ли вы добавить кусок кода для просмотра? - person lucke84; 16.08.2012
comment
Я использую плагин :spock:0.6. Я никогда не объявляю mainContext как переменную. Я обновил вопрос своим тестовым кодом - person Tomas Romero; 17.08.2012
comment
Я думаю, что вы смешиваете модульные тесты и интеграционные тесты. Интеграционный тест предназначен не для тестирования доменного класса (с аннотацией testfro), а для службы или набора утилит (например, именованных запросов). В любом случае, я собираюсь отредактировать свой ответ, пытаясь использовать код, который вы добавили к вопросу. - person lucke84; 17.08.2012
comment
Позже я загружу код controllerSpec, который вызывает ту же проблему. Должен ли я использовать модульные тесты здесь? - person Tomas Romero; 17.08.2012
comment
Основываясь на опубликованном вами коде, я смог исправить спецификацию моего контроллера. Ошибка, с которой я столкнулся, заключалась в том, что я использовал @TestFor(JugadorControllerSpec) - person Tomas Romero; 18.08.2012
comment
Рад, что это было полезно для вас :) - person lucke84; 19.08.2012

Принятый выше ответ хорош для модульных тестов контроллеров, которым необходимо вводить классы обслуживания.

Если вы определили другие управляемые bean-компоненты Spring в resources.groovy и нуждаетесь в их внедрении, вы можете добавить эту строку вверху вашего класса спецификации.

static loadExternalBeans = true //<-- loads resources.groovy beans

Источник: http://grails.github.io/grails-doc/2.4.4/guide/testing.html#unitTesting

Добавление статического определения поля loadExternalBeans = true в класс модульного теста заставляет среду выполнения модульного теста Grails загружать все определения компонентов из файлов grails-app/conf/spring/resources.groovy и grails-app/conf/spring/resources.xml.

person dbrin    schedule 17.12.2015