2013-02-28 64 views
5

使用Grails 2.1.0Grails控制器在渲染模板時測試關於模型的斷言?

看來,從控制器這樣做:

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. 讓人難以對相關模型條目進行多重斷言。

當控制器呈現模板時,是否有任何方法可以更直接地從測試用例中獲取模型中的條目?

+0

'controller.modelAndView.model'不存在? – 2013-02-28 17:09:36

+0

@SérgioMichels正確,'controller.modelAndView'爲空。請記住,這是使用慣用的Grails 2風格,其中測試被聲明爲「@TestFor(WhateverController)」,測試不會擴展任何東西。我不確定modelAndView是否適用於Grails 1,或者爲什麼我總是看到這個建議,但它不在Grails 2的這種類型的測試中。 – Rod 2013-02-28 19:26:01

回答

9

在渲染方法的代碼中挖掘一點(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' 

} 
+0

是的,那工作。有點令人驚訝,它需要這種欺騙。 我已經採取了你的解決方案更進一步,而不是templateModel我實際上分配在控制器實例modelAndView,使其餘的代碼工作就像你期望,如果它是一個視圖 – Rod 2013-02-28 20:30:52

+0

嗯,你可以提出一個[JIRA](http://jira.grails.org/browse/GRAILS),要求更好地訪問模板模型到您的測試。這是改進之美:) – 2013-02-28 20:37:08