I’m busy working on the UrlMappings section of Grails in Action (2nd Edition) and have been discovering a few interesting tidbits that don’t turn up in the docs (at least not that I know of, at time of writing).

One of them relates to testing more complex UrlMapping setups. For instance, here are a couple of interesting examples to get you thinking:

class UrlMappings {

    static mappings = {
         // other mappings here...

        "/timeline/chuck_norris" {
            controller = "post"
            action = "timeline"
            id = "chuck_norris"
        }

        "/users/$id" {
            controller = "post"
            action = "timeline"
        }

    }
}

So we have two mappings in place here. Both map to controller and action, with one setting a static id of “chuck_norris” and the other parsing the $id off the url. In both cases we end up inside the Post controller and fire off the timeline action.

To test this bad boy, we want to test the mapping to action and controller, but we also want to test the params that we have either (a) parsed out of the url; or (b) set within the mapping block.

The magic you need to know is that assertForwardUrlMapping takes an optional closure as the final parameter. Inside that closure, you assign the values to expect to receive, and UrlMappingsUnitTestMixin will do the heavy work of comparison for you. Enter the Spec….

import com.grailsinaction.PostController
import grails.test.mixin.Mock
import grails.test.mixin.TestFor
import spock.lang.Specification

@TestFor(UrlMappings)
@Mock(PostController)
class UrlMappingsSpec extends Specification {

    def "Ensure basic mapping operations for user permalink"() {

        expect:
        assertForwardUrlMapping(url, controller: expectCtrl, action: expectAction) {
            id = expectId
        }

        where:
        url                     | expectCtrl| expectAction  | expectId
        '/users/glen'           | 'post'    | 'timeline'    | 'glen'
        '/timeline/chuck_norris'| 'post'    | 'timeline'    | 'chuck_norris'
    }

}

Just remember, the Closure takes a set of assignments (id = ‘abc’) not comparisons (id == ‘abc’) and you’re in business.

We have a truckload of tests like these in Grails In Action 2, so if you’re into this style of experimenting, you’re going to enjoy reading the samples.

Go forth and test your complex mappings!