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: '[email protected]',
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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With