将模拟服务注入到Grails单元测试的域类中?

时间:2013-08-08 17:31:11

标签: unit-testing testing grails groovy spock

我正在Grails 2.1.1下编写一些基于Spock规范的单元测试。我无法将springSecurityService注入我单位使用的域对象中。

这是我到目前为止所拥有的,

@Mock([SecUser])
@TestFor(FooService)
class FooServiceSpec extends Specification {

    def "test some stuff"() {
        given:
        def mockSecUserService = Mock(SecUserService)
        mockSecUserService.emailValid(_) >> { true }
        mockSecUserService.checkUsername(_) >> { null }
        service.secUserService = mockSecUserService

        def mockSpringSecurityService = Mock(SpringSecurityService)
        mockSpringSecurityService.encodePassword(_) >> { 'tester' }
        // FIXME this needs to be injected somehow

        def params = [
                email: 'unittest@test.com',
                username: 'unittester',
                password: 'tester',
                password2: 'tester'
        ]

        when:
        def result = service.createUser(params)

        then:
        // test results
    }
}

所以会发生的事情是我的测试服务会抛出NullPointerException,因为不会注入mockSpringSecruityService。我的服务中的createUser调用验证了一些参数,然后创建了一个SecUser域对象。

SecUser注入了以下服务以支持密码编码,

class SecUser {
    transient springSecurityService

我无法弄清楚的是以域名类可用的方式注入此服务。我知道有一些帖子已经与此主题相关但其中大多数都假设测试可以实例化域对象,但在我的情况下,实例化是正在测试的单元的一部分。

我尝试了以下代替FIXME,

defineBeans {
    mockSpringSecurityService(SpringSecurityService) { bean -> 
        bean.autowire = true
    }
}

但结果我得到了跟随错误,

  

| groovy.lang.MissingMethodException:没有方法签名:   grails.plugins.springsecurity.SpringSecurityService.call()是   适用于参数类型:(java.lang.Class,   skillz.GameAccountServiceSpec $ _spock_feature_0_0_closure4_closure5)   值:[class grails.plugins.springsecurity.SpringSecurityService,   ...]可能的解决方案:wait(),any(),find(),dump(),collect(),   的grep()

有什么想法吗?

1 个答案:

答案 0 :(得分:6)

我最终做的工作是,

SecUser.metaClass.encodePassword = { null }

在我的域对象encodePassword中是使用springSecurityService bean的方法。因此,如果我理解正确,这只是覆盖此方法什么都不做(方法是无效的)。

我更喜欢使用metaClass来虚拟注入bean,但我尝试

SecUser.metaClass.getSpringSecurityService = { mockSpringSecurityService }

当encodePassword尝试使用SpringSecurityService时,会使用NPE。

我觉得这是一个不太理想的工作,所以我喜欢有人给出一个不那么讨厌的答案。