在Grails Spock规范测试中注入依赖项

12

我需要在我的测试中将依赖项注入到域对象中。

这些测试位于test/integration目录下,并扩展自spock.lang.Specification

我该如何实现?

注意:我看过这篇帖子如何将spring bean注入到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)

@AutoWired,也许?当你运行测试时,你的Grails应用程序是否在运行? - Will
也许模拟这些依赖关系是一个更好的主意?哪些依赖项没有被注入?编写一些示例代码以显示问题。 - Tomasz Kalkosiński
我从未尝试在Grails中使用@Autowired,我会试一下。 当我运行测试时,我没有运行应用程序。 - Tomas Romero
我已经更新了我的问题并添加了更多数据,稍后我会添加代码。 - Tomas Romero
2个回答

12

尝试在测试中声明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:
         // ....
 }

您可以使用单元测试来测试服务,具体要测试什么取决于您要测试的是一个类(即服务)还是一种“情境”(即服务的使用方式)。

附注:当然,这里的代码未经测试,可能包含错别字。 :) 但我希望您能理解如何进行测试。


在进行集成测试时,您应该扩展IntegrationSpec https://code.google.com/p/grails-spock-examples/wiki/Overview#Integration_tests 您是否有声明null mainContext的点?您目前使用的Spock插件版本是哪个?您能添加一段代码让我们看看吗? - lucke84
我正在使用插件“:spock:0.6”。我从未将mainContext声明为变量。我已经在问题中更新了我的测试代码。 - Tomas Romero
我认为你混淆了单元测试和集成测试。集成测试不是用来测试域类(带有testfro注释),而是用来测试服务或一堆工具(如命名查询)。无论如何,我将编辑我的答案,尝试使用您在问题中添加的代码。 - lucke84
根据您发布的代码,我成功纠正了我的控制器规范。我遇到的错误是我使用了@TestFor(JugadorControllerSpec)。 - Tomas Romero
很高兴这对你有用 :) - lucke84
显示剩余2条评论

1
上面接受的答案适用于需要注入服务类的控制器的单元测试。
如果您在resources.groovy中定义了其他Spring托管的bean并需要它们被注入,您可以在规范类的顶部添加此行。
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文件中加载所有bean定义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接