Grails控制器在渲染模板时测试关于模型的断言?

时间:2013-02-28 17:00:02

标签: grails

使用Grails 2.1.0

似乎从控制器执行此操作:

render(view: "someView", model: [modelEntry: "hello"]) 

允许我在该控制器的单元测试中执行此操作:

controller.method() 
assert model.modelEntry == "hello" 

但是,如果我更改控制器来执行此操作:

render(template: "someTemplate", model: [modelEntry: "hello"]) 

现在测试中的模型实例是一个空数组。我已经做了很多搜索,大多数解决方案似乎都是Grails 1,通常涉及modelAndView对象(在我的测试中不存在)或renderArgs(同上)。

我发现的唯一解决方案是手动覆盖测试中的视图,如下所示:

views['_someTemplate.gsp'] = '${modelEntry}'

然后对字符串进行断言。但我不喜欢这个解决方案,因为它:

  1. 要求测试知道模板的文件名
  2. 使测试没有良好toString()方法的模型条目变得困难
  3. 使得很难对相关的模型条目进行多次断言。
  4. 当控制器呈现模板时,有没有办法更直接地从测试用例中获取模型中的条目?

1 个答案:

答案 0 :(得分:10)

在渲染方法的代码中挖掘一点(org.codehaus.groovy.grails.web.metaclass.RenderDynamicMethod)我可以看到modelAndView仅在渲染view时设置。

渲染模板确实会返回null modelAndView。

在这种情况下检查模型我认为你可以使用Groovy metaClass。想法是截取原始方法,存储值然后给他打电话。

基于this question,我建立了这个(未经测试,可能需要调整):

@TestFor(MyController)
class MyControllerTests

  def templateModel

  @Test
  void inspectTemplateModel() {
    def originalMethod = MyController.metaClass.getMetaMethod('render', [Map] as Class[])
    controller.metaClass.render = { Map args ->
      templateModel = args.model
      originalMethod.invoke(delegate, args)
    }

    controller.method()
    assert templateModel.modelEntry == 'foo'

}