Testing Controllers

Last updated by phoet 8 months ago

Unit & Integration Testing Controllers

Unit Testing

Basically the same thing as below, however the database will not be started.

Integration Testing

The shortest way to write an integration test for a controller is to extend the grails.test.ControllerUnitTestCase class. In its setUp() method, it creates an instance of your controller class with all the dynamic methods already injected.

For this to work, you must follow the following convention:

  • Your test class needs to be in the same package as the controller class under test
  • The name of your test class needs to be "<YourControllerName>Tests"
Essentially Grails automatically configures each test with a mock request, response, and session which you can then use to perform your tests. For example consider the following controller:
package com.acme.sampleapp

class FooController {

def someRender = { render "bar" }

def someRedirect = { redirect(action:"bar") } }

The tests for this would be:
package com.acme.sampleapp  // must be the same package!

class FooControllerTests extends grails.test.ControllerUnitTestCase {

void testSomeRender() { controller.someRender() assertEquals "bar", controller.response.contentAsString }

void testSomeRedirect() { controller.someRedirect() assertEquals "bar", controller.redirectArgs.action } }

In the above case the response is an instance of MockHttpServletResponse which we can use to obtain the {{contentAsString}} (when writing to the response).

NOTE: contentAsString is only written to when the controller is rendering text (render text: "Hello World"). A controller that returns a model that would be rendered by a view engine will not occur from a controller test.

Integration Tests for Controllers with Services

If your controller references a service (or other injected bean), you have to explicitly initialise the service from your test. e.g.

class FilmStarsController {
    def popularityService

def update = { // do something with popularityService }

}

In your test you need to set the service as below

class FilmStarsControllerTests extends grails.test.ControllerUnitTestCase {
  def popularityService

public void testInjectedServiceInController () { controller.popularityService = popularityService controller.update() } }

Integration Testing Views

Testing a view involves passing data to a template that produces HTML and verifying that the template produces the correctly formatted output. View testing can produce brittle test suites so it is a good ideal to limit view testing to key areas such as checking the data that appears on the pages only. Checking of styles and html tags is not recommended.

Grails supports the testing of view using this groovy test case base class. More details can be found User Guide - Unit Testing

GroovyPagesTestCase

How the mock request & response work

ControllerUnitTestCase.setup() calls mockController() which in turn calls grails.test.MockUtils.mockController(). If you want to understand where the magic properties named renderArgs, redirectArgs, etc. come from and how they work, learn from the source code of the MockUtils class.