Skip to content

Instantly share code, notes, and snippets.

@berngp
Created April 13, 2011 19:26
Show Gist options
  • Save berngp/918221 to your computer and use it in GitHub Desktop.
Save berngp/918221 to your computer and use it in GitHub Desktop.
ThrowableXMLMarshallerSpec.groovy
package org.osscripters.grails.common.web.converters.marshaller
import grails.converters.XML
import org.codehaus.groovy.grails.web.converters.exceptions.ConverterException
import org.codehaus.groovy.grails.web.converters.marshaller.NameAwareMarshaller
import org.gcontracts.annotations.Requires
/**
* User: berngp
* Date: 4/12/11
* Time: 2:48 PM
*/
class ThrowableXMLMarshaller extends
ContextAwareObjectMarshallerTemplate<XML> implements NameAwareMarshaller {
boolean supports(Object object) {
object instanceof Throwable
}
@Requires({ supports(object) })
void marshalObject(Object object, XML xml) throws ConverterException {
Throwable throwable = (Throwable) object
try {
xml.startNode('type').chars( throwable.class.name as String ).end()
xml.startNode('message').chars( getMessage(throwable.message) ?: throwable.message).end()
}
catch (ConverterException ce) {
throw ce
}
catch (anyOtherException) {
throw new ConverterException("Error converting Bean with class ${object.class.name}",
anyOtherException)
}
}
String getElementName(Object o) {
'error'
}
}
package org.osscripters.grails.common.web.converters.marshaller
import grails.converters.XML
import grails.plugin.spock.ControllerSpec
import javax.servlet.http.HttpServletResponse
import org.codehaus.groovy.grails.support.MockApplicationContext
import org.codehaus.groovy.grails.web.converters.ConverterUtil
import org.codehaus.groovy.grails.web.converters.configuration.ConvertersConfigurationInitializer
import org.custommonkey.xmlunit.Diff
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.validation.Errors
import org.springframework.web.context.WebApplicationContext
/**
* User: berngp
* Date: 4/12/11
* Time: 2:48 PM
*/
class ThrowableXMLMarshallerSpec extends ControllerSpec {
private static final Logger log = LoggerFactory.getLogger(ThrowableXMLMarshallerSpec)
def expectedMarkupTemplate = { Map args ->
"""<?xml version="1.0" encoding="UTF-8"?><error><type>${args.type}</type><message>${args.message}</message></error>"""
}
def applicationContext
def setup() {
mockApplicationContext()
registerDefaultConverters()
registerCustomConverters()
}
def 'marshall throwable'() {
given: 'a throwable that the controller will send'
controller.throwable = new IllegalStateException('Expected Message')
and: 'a expected xml that should be returned by the controller'
String expectedXml = expectedMarkupTemplate(type: controller.throwable.class.name,
message: controller.throwable.message)
when: 'we call the controller'
controller.testThrowable()
and: 'get the response'
String obtainedXml = mockResponse.contentAsString
and: 'build our xmlDiff object'
def xmlDiff = new Diff(obtainedXml, expectedXml)
then: 'we assert that the xmls are similar'
assert xmlDiff.similar(), "${obtainedXml} == ${expectedXml}"
}
def provideMvcClassUnderTest() {
TestController.class
}
protected WebApplicationContext mockApplicationContext() {
applicationContext = new MockApplicationContext()
applicationContext
}
protected void registerDefaultConverters() {
def convertersInit = new ConvertersConfigurationInitializer()
convertersInit.initialize()
[List, Set, Map, Errors].each { addConverters(it) }
}
protected void registerCustomConverters() {
//For unit testing add the a direct impl. of a Throwable, if not
//the metaclass is not cleaned properly after the test ends (cleanup).
addConverters(IllegalStateException)
XML.registerObjectMarshaller(new ThrowableXMLMarshaller())
}
protected void addConverters(Class clazz) {
registerMetaClass(clazz)
clazz.metaClass.asType = {Class asClass ->
if (ConverterUtil.isConverterClass(asClass)) {
return ConverterUtil.createConverter(asClass, delegate, applicationContext)
}
else {
return ConverterUtil.invokeOriginalAsTypeMethod(delegate, asClass)
}
}
}
class TestController {
Throwable throwable
def testThrowable = {
response.status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR
withFormat {
xml { render throwable as XML }
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment