代码之家  ›  专栏  ›  技术社区  ›  Dave Bower Ekaterina Zdorov

如何模拟/存根调用Grails控制器中的消息taglib

  •  6
  • Dave Bower Ekaterina Zdorov  · 技术社区  · 15 年前

    我有一个Grails控制器,它依赖消息taglib来解析i18n消息:

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

    我为控制器编写了一个单元测试:

    class TokenControllerTests extends ControllerUnitTestCase {
    
    void testPasswordResetInvalidTokenRedirect() {
    
        controller.passwordReset()
        assert...
    }
    }
    

    因为消息taglib在控制器中被调用,所以我得到一个MissingMethodException:

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

    有人知道在单元测试中解决这个问题的最佳方法吗?理想情况下,我希望对消息执行断言,但现在如果测试刚刚运行,我会很高兴的!

    谢谢

    4 回复  |  直到 13 年前
        1
  •  8
  •   Derek    15 年前

    您可以在测试中动态添加缺少的方法。 不确定这是否是100%正确的,但类似于……

    void testPasswordResetInvalidTokenRedirect() {
        controller.metaClass.message = { LinkedHashMap arg1 -> return 'test message output'}
        controller.passwordReset()
        assert...
    }
    
        2
  •  5
  •   Burt Beckwith    15 年前

    您可以使用元类连接它,比如:

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

    这将始终返回相同的消息(假设您并不真正关心值是什么),但如果需要,您可以添加逻辑,即检查“code”的值并返回相应的字符串。

        3
  •  2
  •   Dave Bower Ekaterina Zdorov    15 年前

    除了尝试上述答案之外,我还决定解析GSP中的消息,从而将对标记lib的依赖全部移除。

    我的课程代码如下:

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

    在GSP中,我有:

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

    解决方案灵感来自 the grails docs

    当然,德里克和伯特的答案适用于所有的标签库,所以是更一般的解决方案。

        4
  •  0
  •   Mutix question    13 年前

    我认为这是最好的方法…

    在调用Controller方法之前将其放入测试中:

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