views:

853

answers:

4

I've got a Grails controller which relies on the message taglib to resolve an i18n message:

class TokenController {
def passwordReset = {
    def token = DatedToken.findById(params.id);
    if (!isValidToken(token, params)) {
        flash.message = message(code: "forgotPassword.reset.invalidToken")
        redirect controller: 'forgotPassword', action: 'index'
        return
    }
    render view:'/forgotPassword/reset', model: [token: token.token]
}
}

I've written a unit test for the controller:

class TokenControllerTests extends ControllerUnitTestCase {

void testPasswordResetInvalidTokenRedirect() {

    controller.passwordReset()
    assert...
}
}

Since the message taglib is called in the controller I get a MissingMethodException:

groovy.lang.MissingMethodException: No signature of method: TokenController.message() is applicable for argument types: (java.util.LinkedHashMap) values: [[code:forgotPassword.reset.invalidToken]]

Does anyone know the best way to get around this issue in a unit test? Ideally I would like to perform assertions on the message but right now I'd be happy if the test just ran!

Thanks

+2  A: 

You could dynamically add the missing method in your test. Not sure if this is 100% correct but something like....

void testPasswordResetInvalidTokenRedirect() {
    controller.metaClass.message = { LinkedHashMap arg1 -> return 'test message output'}
    controller.passwordReset()
    assert...
}
Derek
Thanks Derek, that works a treat. In the mean time I've changed my code to resolve the message in the gsp as that seemed much neater than doing it in the controller.
Dave
+2  A: 

You can wire it up using the Metaclass, something like:

void testPasswordResetInvalidTokenRedirect() {

   TokenControllerTests.metaClass.message = { Map p -> return "foo" }
   controller.passwordReset()
   assert...
}

This returns the same message always (assuming you don't really care what the value is) but you can add logic if you want, i.e. check the value of 'code' and return a corresponding string.

Burt Beckwith
+2  A: 

As well as trying the above answers, I decided to resolve the message in the gsp and so remove the dependency on the tag lib all together.

My code for the class now looks like:

if (!isValidToken(token, params)) {
    flash.message = "forgotPassword.reset.invalidToken"

And in the gsp I have:

<g:message code="${flash.message}" args="${flash.args}" default="${flash.defaultMsg}"/>

A solution inspired by the grails docs

Of course Derek and Burt's answers work for all tag libs so are more general solutions.

Dave
A: 

i think this is the best way...

put this in the test just before calling the controller method

controller.metaClass.message = { LinkedHashMap key -> assertEquals 'please.create.business', key.code}

ew