2

I'm trying to write some integration tests for a controller that handles REST requests in JSON format. My controller defines() create like this:

class FooController {
    ...
    def create() {
        withFormat {
            html {
                [fooInstance: new Foo(params)]
            }
            json {
                [fooInstance: new Foo(params.JSON)]
            }
        }
    }
    ...
}

And then I have an integration test that looks like this:

@TestFor(FooController)
class FooControllerTests extends GroovyTestCase {
    void testCreate() {
        def controller = new FooController()

        controller.request.contentType = "text/json"

        // this line doesn't seem to actually do anything
        controller.request.format = 'json'

        // as of 2.x this seems to be necessary to get withFormat to respond properly
        controller.response.format = 'json'

        controller.request.content = '{"class" : "Foo", "value" : "12345"}'.getBytes()

        def result = controller.create()

        assert result

        def fooIn = result.fooInstance

        assert fooIn
        assertEquals("12345", fooIn.value)
    }
}

But fooIn is always null. If I debug the test, I can see that when FooController.create() is invoked, params is empty too. Admittedly I don't know much about how the integration tests are supposed to function internally but I expected to see data representing my Foo instance.

Any ideas?

Nick
  • 8,181
  • 4
  • 38
  • 63

1 Answers1

0

You're using withFormat to render your content, so although it is a map in your controller code, the response is actually a String.

AbstractGrailsMockHttpServletResponse provides what you need (along with other helpful methods) and controller.response is an instance of this during tests:

http://grails.org/doc/2.1.0/api/org/codehaus/groovy/grails/plugins/testing/AbstractGrailsMockHttpServletResponse.html#getJson()

So what you want is something like this:

controller.create()

def result = controller.response.json

Edit:

As you asked, you should be passing your params like this:

controller.params.value = "12345"
controller.params.'class' = "Foo"
Rhysyngsun
  • 951
  • 6
  • 17
  • I tried using your suggestion but it looks like controller.response is empty(zero length). Debugging and breaking in FooController.create() shows that params.JSON is null as well, so it seems like there must be an issue with how I am passing in the request content? – Nick Mar 28 '13 at 20:02
  • That gets me closer for sure. Do you know of a way to take an instance of an Domain object (Foo in my case) and then marshall it into params for consumption by controller.create()? – Nick Mar 29 '13 at 02:27
  • Oh and while using the above does show that params is populated with values when I break into FooController.create(), params.JSON is still null, thus causing create() to also return nothing. – Nick Mar 29 '13 at 02:40
  • See (http://stackoverflow.com/questions/6343264/grails-groovy-domain-object-map-of-its-properties) to get params from a domain objefct. – Todd Murray Mar 29 '13 at 15:33