Testing URL Mappings
Basics
URL mapping test cases must extend
grails.test.GrailsUrlMappingsTestCase and should live in
test/integration .
URL mapping tests take an application relative URL, and assert that; it is mapped to a controller and/or action or view, the params contained within the URL are extracted as expected, and that the destination
actually exists. That is, if you are testing a URL mapping that would map to the controller
BookController , and you assert this controller but it doesn't actually exist… the assertion will fail. This applies to controllers, actions
and views. It also tests for mapping to default actions of controllers where applicable.
Specifying the mappings to test
By default, the test case will load
all of the mappings that you have defined in your application. However if you have your mappings defined over several classes you can specify the mappings to test by defining a
static mappings property as either a single url mappings class or a list or url mapping classes.
Example…
class UrlMappingTests extends GrailsUrlMappingsTestCase
{
static mappings = UrlMappings
}Or…
class UrlMappingTests extends GrailsUrlMappingsTestCase
{
static mappings = [UrlMappings, OtherUrlMappings]
} forward URL mappings">Asserting forward URL mappings
The term "forward URL mapping" refers to asserting that a given URL maps to a handler within your grails app, whether that be an action or a view.
Given the following standard URL mappings…
/controller/action?/id?()
And the following controller…
class BookController
{
def defaultAction = "list" def list = { /* */ }
def save = { /* */ }
def show = { /* */ }
}We would test them like…
assertForwardUrlMapping("/book", controller: "book", action: "list")
assertForwardUrlMapping("/book/save", controller: "book", action: "save")
assertForwardUrlMapping("/book/show", controller: "book", action: "show")Remember that tests for actions or controllers that don't exist will fail…
assertForwardUrlMapping("/book/delete", controller: "book", action: "delete") // this will failTesting embedded parameters
@assertForwardUrlMapping()@ can optional take a closure that defines the embedded parameters to test for in the URL mapping…
assertForwardUrlMapping("/book/show/32", controller: "book", action: "show") {
id = 32
}Mapping to views
Views are tested for just like actions…
assertForwardUrlMapping("/stats", view: "stats")Testing HTTP response code mappings
HTTP response code mappings can be tested by specifying the HTTP response code as an integer…
assertForwardUrlMapping(500, view: "error")
reverse URL mappings">Asserting reverse URL mappings
The term "reverse URL mapping" refers to asserting that redirecting or creating a link to the specified action or view with the specified parameters would map to the specified URL…
assertReverseUrlMapping("/book/show", controller: "book", action: "show")Or…
assertReverseUrlMapping("/book/show/25", controller: "book", action: "show") {
id = 25
}All of the same rules that apply to testing the forward mappings apply to testing the reverse mappings.
forward and reverse mappings simultaneously">Asserting the forward and reverse mappings simultaneously
The method
assertUrlMappings() has the same signature as
assertForwardUrlMapping() and
assertReverseUrlMapping() . If applicable, the
forward mapping is tested, then the
reverse mapping. For the
reverse mapping to be tested, a controller has to be specified and the URL must not be a http response code integer.
assertUrlMapping("/book/show/32", controller: "book", action: "show") {
id = 32
}Example
class UrlMappings {
static mappings = {
"/$user"(controller: "user", action: "show") {
constraints {
user(matches: /^[p{Digit}].*$/) // Users must start with a number
}
}
"/$user/$msgid"(controller: "user", action: "showMessage") {
constraints {
user(matches: /^[p{Digit}].*$/) // Users must start with a number
}
}
"/icon/$id?"(controller: "icon")
"/credits"(controller: "credits", view: "credits")
"500"(view: "error")
}
}Assuming all of those controllers, actions and views exist…
class UrlMappingsTests extends grails.test.GrailsUrlMappingsTestCase { void testUserMappings() {
assertUrlMapping("/123", controller: "user", action: "show") {
user = "123"
}
assertUrlMapping("/456/abc", controller: "user", action: "showMessage") {
user = "123"
msgid = "abc"
}
} void testAdminMappings() {
assertUrlMapping("/icon", controller: "icon", action: "index") { // assuming 'index' is the default action of the admin controller
id = null
}
assertUrlMapping("/icon/123", controller: "icon") { // can leave action out
id = "123"
}
} void testCreditsMappings() {
assertUrlMapping("/credits", controller: "credits", view: "credits")
} void testErrorMappings() {
assertUrlMapping(500, view: "error")
}}