Search code examples
jsongrailsserializationgrails-2.0

How do I unit test a Grails service that uses a converter?


I have a Grails service that sends out e-mails using a 3rd-party service by doing a HTTP call:

class EmailService {
    def sendEmail(values) {
        def valueJson = values as JSON
        ... // does HTTP call to 3rd party service
    }
}

I've written a unit test to test this service (because an integration test spins up Hibernate and the entire domain framework, which I don't need):

@TestFor(EmailService)
class EmailServiceTests {
    void testEmailServiceWorks() {
        def values = [test: 'test', test2: 'test2']
        service.sendEmail(values)
    }
}

However, when I execute this unit test, it fails with this exception when it tries to do the as JSON conversion:

org.apache.commons.lang.UnhandledException: org.codehaus.groovy.grails.web.converters.exceptions.ConverterException: Unconvertable Object of class: java.util.LinkedHashMap

I then re-wrote my unit test to just do the following:

void testEmailServiceWorks() {
    def value = [test: 'test', test2: 'test2']
    def valueJson = value as JSON
}

And I get the same exception when it tries to do the as JSON conversion.

Does anyone know why I'm getting this exception, and how I can fix it?


Solution

  • The as JSON magic is created when the domain framework spins up.

    You have to either change your test to an integration one or mock the asType.

    def setUp(){
        java.util.LinkedHashMap.metaClass.asType = { Class c ->
            new grails.converters."$c"(delegate)
        }
    }
    

    Rember to clean up after yourself in the tearDown, you wouldn't want metaprogramming leaks in your test suite.

    def tearDown(){
        java.util.LinkedHashMap.metaClass.asType = null
    }
    

    Edit: If you come from the future, consider this answer: https://stackoverflow.com/a/15485593/194932