Unit Testing in Grails is very easy. If you are not familiar with this, you should definitely check out the reference manual about it. Today however, I was writing some REST services that return XML. The controller does content negotiation and can, depending on the request, return HTML or XML. Of course I also wanted to write a test for it, but I couldn't find how to do it in the documentation. It turns out to be very easy, but I wanted to share how I did it.
First a simple version of a controller that supports content negotiation:
def list = {
def myContact = new Contact(firstname: 'Paul', lastname: 'Bakker')
withFormat {
html {
[contact: myContact]
}
xml {
render(contentType: "application/xml") {
contact {
firstname(myContact.firstname)
lastname(myContact.lastname)
}
}
}
}
}
The withFormat block chooses, depending on the request, the response to build. If this controller is requested with a normal URL from a browser, HTML will be returned. If the Accept header is set, or if the URL is postfixed '.xml', XML will be returned however. This is all documented well in the reference documentation, so you can read the details there. If the controller is requested for XML, the following XML will be returned:
<contact>
<firstname>Paul</firstname>
<lastname>Bakker</lastname>
</contact>
Next I wanted to write a Unit Test for this controller. There are two special things about testing a controller that does content negotiation:
- Request the correct content type
- Test if the response is generated correctly
For the first step you should first understand how the controller figures out what content type to return. When Grails processes a request, it will check both the Accept header and the URL extension (note that the Accept header is not enabled by default!). It will set a variable request.format with the value that is defined in the mime.types configuration in Config.groovy for that request format. So concluding, you'll need to set the request.format variable in the test, which is very easy.
controller.request.format = 'xml'
Note that the controller variable in the example is the implicitly created controller by the ControllerUnitTestCase.
Next you should invoke the controller and check the XML returned by the controller. This is what I couldn't find in the documentation. After invocation you can access the response using:
controller.response.getContentAsString()
This contains the XML as a String, which you can parse using XmlParser. Easy! The complete test is displayed below. Note that only the XML request is tested. You should add another test to test the HTML response.
void testListInXML() {
controller.request.format = 'xml'
controller.list()
def contact = new XmlParser().parseText(controller.response.getContentAsString())
assert contact.firstname.text() == 'Paul'
assert contact.lastname.text() == 'Bakker'
}
Posted
20-08-2009 17:06
by
Paulb