2010-01-06 2 views
6

J'ai un contrôleur Grails qui repose sur le taglib de message pour résoudre un message i18n:Comment se moquer/stub appelle à taglib message dans le contrôleur Grails

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

J'ai écrit un test unitaire pour la contrôleur:

class TokenControllerTests extends ControllerUnitTestCase { 

void testPasswordResetInvalidTokenRedirect() { 

    controller.passwordReset() 
    assert... 
} 
} 

Depuis le taglib message est appelé dans le contrôleur je reçois un MissingMethodException:

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

Quelqu'un connaît-il le meilleur moyen de contourner ce problème lors d'un test unitaire? Idéalement, je voudrais effectuer des affirmations sur le message, mais maintenant je serais heureux si le test venait de courir!

Merci

Répondre

2

En plus d'essayer les réponses ci-dessus, j'ai décidé de résoudre le message dans le fichier gsp et de supprimer ainsi la dépendance à la balise lib ensemble.

Mon code pour la classe ressemble maintenant:

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

Et dans le gsp je:

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

Une solution inspirée the grails docs

des réponses de cours Derek et Burt travail pour toutes les bibliothèques de tags, il existe des solutions plus générales.

+0

je puis ajouter ceci à votre code: flash.args = [some, args] – Eldelshell

8

Vous pourriez ajouter dynamiquement la méthode manquante dans votre test. Je ne sais pas si cela est 100% correct, mais quelque chose comme ....

void testPasswordResetInvalidTokenRedirect() { 
    controller.metaClass.message = { LinkedHashMap arg1 -> return 'test message output'} 
    controller.passwordReset() 
    assert... 
} 
+0

Merci Derek, qui fonctionne un régal. Pendant ce temps, j'ai changé mon code pour résoudre le message dans le GSP car cela semblait beaucoup plus propre que de le faire dans le contrôleur. –

+1

Donc, si vous faites cela, il se fera l'écho de retour le code du message: 'myController.metaClass.message = {LinkedHashMap args -> retour "$ {} args.code"}' Par exemple: 'vide testShow_NoSuch() { myController.params.id = 999 modèle def = myController.show() modèle assertNull assertEquals de la default.not.found.message de ', myController.flash.message }' –

5

Vous pouvez câbler à l'aide de la métaclasse, quelque chose comme:

void testPasswordResetInvalidTokenRedirect() { 

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

Cela renvoie le même message toujours (en supposant vous ne vous souciez pas vraiment de la valeur) mais vous pouvez ajouter de la logique si vous le souhaitez, c'est-à-dire vérifier la valeur de 'code' et renvoyer une chaîne correspondante.

0

Je pense que c'est la meilleure façon ...

Mettre cela dans le test juste avant d'appeler la méthode du contrôleur:

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