简体   繁体   English

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

[英]Injecting a mock service into a domain class for a Grails unit test?

I am writing some Spock spec based unit tests under Grails 2.1.1. 我正在Grails 2.1.1下编写一些基于Spock规范的单元测试。 I'm having trouble getting springSecurityService injected into my domain object that is used by my unit. 我无法将springSecurityService注入到我的单元使用的域对象中。

This is what I have so far, 这是我到目前为止,

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

So what happens is that my service being test throws a NullPointerException because the mockSpringSecruityService is not injected. 所以会发生的事情是我的测试服务会抛出NullPointerException因为不会注入mockSpringSecruityService。 The createUser call in my service validates some params and then creates a SecUser domain object. 我的服务中的createUser调用验证一些参数,然后创建一个SecUser域对象。

The SecUser has the following service injected into it to support password encoding, SecUser注入了以下服务以支持密码编码,

class SecUser {
    transient springSecurityService

What I can't figure out out is inject this service in way that it is available to the domain class. 我无法弄清楚的是以域类可用的方式注入此服务。 I know there are a few posts already relating to this subject but most of them assume the test can instantiate the domain object, but in my case the instantiation is part of the unit being testing. 我知道有一些帖子已经与这个主题相关,但是大多数帖子都认为测试可以实例化域对象,但在我的情况下,实例化是被测单元的一部分。

I've tried the following in place of the FIXME, 我试过以下代替FIXME,

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

But as a result I get the follow error, 但结果我得到了跟随错误,

| | groovy.lang.MissingMethodException: No signature of method: grails.plugins.springsecurity.SpringSecurityService.call() is applicable for argument types: (java.lang.Class, skillz.GameAccountServiceSpec$_spock_feature_0_0_closure4_closure5) values: [class grails.plugins.springsecurity.SpringSecurityService, ...] Possible solutions: wait(), any(), find(), dump(), collect(), grep() 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()

Any ideas? 有任何想法吗?

What I ended up doing as a work around is, 我最终做的工作是,

SecUser.metaClass.encodePassword = { null }

In my domain object encodePassword is the method that uses the springSecurityService bean. 在我的域对象中, encodePassword是使用springSecurityService bean的方法。 So if I understand this correctly, this just overwrites this method to do nothing (the method is a void). 因此,如果我理解正确,这只是覆盖此方法什么也不做(方法是无效的)。

I'd prefer to use the metaClass to faux inject the bean, but my attempt at 我更喜欢使用metaClass来虚拟注入bean,但是我尝试了

SecUser.metaClass.getSpringSecurityService = { mockSpringSecurityService }

Blows up with an NPE when encodePassword attempts to use SpringSecurityService. 当encodePassword尝试使用SpringSecurityService时,会使用NPE。

I feel like this is a less than ideal work around, so I'd love for someone to give a less hacky answer. 我觉得这是一个不太理想的工作,所以我喜欢有人给出一个不那么讨厌的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM