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

孤者浪人 提交于 2019-12-22 04:47:33

问题


I am writing some Spock spec based unit tests under Grails 2.1.1. I'm having trouble getting springSecurityService injected into my domain object that is used by my unit.

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. The createUser call in my service validates some params and then creates a SecUser domain object.

The SecUser has the following service injected into it to support password encoding,

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,

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()

Any ideas?


回答1:


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. 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

SecUser.metaClass.getSpringSecurityService = { mockSpringSecurityService }

Blows up with an NPE when encodePassword attempts to use SpringSecurityService.

I feel like this is a less than ideal work around, so I'd love for someone to give a less hacky answer.



来源:https://stackoverflow.com/questions/18132363/injecting-a-mock-service-into-a-domain-class-for-a-grails-unit-test

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!