I have some often-used helper methods for unit tests put into a seperate file. The idea is to, for example, allow my XYZTests.groovy to call TestHelper.getUserObject() in order to get a fully initialized instance of User.
Now the problem is, that there’s a springSecurityService.encodePassword(pw) being called in the User’s beforeInsert() which always fails as there’s no mock for springSecurityService in TestHelper.groovy.
java.lang.NullPointerException: Cannot invoke method encodePassword() on null object
In User.groovy:
def beforeInsert() {
// ...
password = springSecurityService.encodePassword(pw)
// ...
}
Note: I would like to avoid any mocking in TestHelper.groovy in order to use it’s methods in integration tests too.
In spite of that, even if I try to call a mockFor() anywhere in the TestHelper.groovy, I get an MME:
No signature of method: static myproject.TestHelper.mockFor() is applicable for argument types: (java.lang.Class, java.lang.Boolean) values: [class grails.plugins.springsecurity.SpringSecurityService, true]
groovy.lang.MissingMethodException: No signature of method: static myproject.TestHelper.mockFor() is applicable for argument types: (java.lang.Class, java.lang.Boolean) values: [class grails.plugins.springsecurity.SpringSecurityService, true]
at myproject.TestHelper.mockSpringSecurityService(TestHelper.groovy:59)
at myproject.TestHelper$mockSpringSecurityService.callStatic(Unknown Source)
at myproject.TestHelper.getUserObject(TestHelper.groovy:47)
at myproject.TestHelper$getUserObject.call(Unknown Source)
at myproject.UserTests.setUp(UserTests.groovy:26)
Note: I currently mock the springSecurityService.encodePassword like this:
// in UserTests.groovy
protected void setUp() {
// mockDomain(...) and such here
def u = TestHelper.getUserObject("Pummel")
u.springSecurityService = mockSpringSecurityService()
assert u.save()
}
private mockSpringSecurityService() {
def ssService = mockFor(SpringSecurityService,true)
ssService.metaClass.encodePassword() { password ->
"08a2d3c63bf9fc88276d97a9e8df5f841fd772724ad10f119f7e516f228b74c6"
}
ssService
}
- Any ideas on how I may be able to use the helper class while leaving all mocking in the unit tests only?
- Where would I best place the TestHelper.groovy file for using it in integration AND unit tests?
Note that everything is working perfectly fine when I move all helpers into UserTests.groovy directly!
The solution to this is to refrain from calling any
user.save()in the TestHelper.groovy.This makes sense, as for many (unit) tests a persisted (saved) instance is unnecessary anyways.
On the other hand many cases actually require an unsaved intance. (In order to test certain effects of the
.save()itself, for example)A working example for integration tests would be:
For a unit tests:
This keeps any mocks out of TestHelper.groovy