Saturday, March 21, 2009

Integration test of Grails controller

The general pattern to test a controller is:

void testBar() {
def ctrl = new FooController()
def testParams = ...
ctrl.params.putAll(testParams)
ctrl.bar()
...
}


Different outcomes are expected from the call to the action:

Redirection


If redirection is expected, the redirected URL can be obtained from ctrl.response.redirectedUrl. Keep in mind that unless GRAILS-4270 is resolved, you will have to make sure that the controller name is specified in the parameter list of redirect(). For example,

def index = {
redirect(action: 'list', params: params)
}

won't work. You need to change it to:

def index = {
redirect(controller: 'foo', action: 'list', params: params)
}


A View Is Rendered


If a view is expected, the parameters passed to render() is actually stored in Spring's ModelAndView object. E.g. if you have the following statement in your controller:

render(view: 'show', model: [ fooInstance: foo ])

You can access foo via:

def foo = ctrl.modelAndView.model.fooInstance


Text Is Rendered Directly


If the action renders some texts directly, the texts can be accessed by

def text = ctrl.response.contentAsString


A Map Is Returned


If a map is returned, as is the case for the scaffolded list action, you can access the map like this:

def map = ctrl.list()

1 comment:

Rob said...

If you extend ControllerUnitTestCase you can write very effective unit tests for controllers that are much faster than integration tests. In assertions you can use controller.renderArgs.view, controller.renderArgs.model, controller.redirectArgs.action, etc.