Reputation: 137
Using Grails 2.1.0
It seems that doing this from a controller:
render(view: "someView", model: [modelEntry: "hello"])
allows me to do this in a unit test for that controller:
controller.method()
assert model.modelEntry == "hello"
However, if I change the controller to do this:
render(template: "someTemplate", model: [modelEntry: "hello"])
Now the model instance in the test is an empty array. I've done quite a bit of searching about this, and most of the solutions seem to be for Grails 1, often involving the modelAndView
object (which doesn't exist in my test) or renderArgs
(ditto).
The only solution I've found is to manually override the views within the test, like this:
views['_someTemplate.gsp'] = '${modelEntry}'
and then making assertions about the string. But I dislike this solution because it:
Is there any way to more directly get at the entries in the model from a test case when the controller renders a template?
Upvotes: 6
Views: 2241
Reputation:
Digging a little bit in the code of the render method (org.codehaus.groovy.grails.web.metaclass.RenderDynamicMethod
) I can see that the modelAndView
is setted only when you render a view
.
Rendering a template will return a null modelAndView indeed.
To inspect the model in this case I think you can use the Groovy metaClass
. The idea is to intercept the original method, store the value and then call him.
Based on this question, I builded this (not tested, may need adjusts):
@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'
}
Upvotes: 10