3

I've been trying to define a test for consuming XML formatted request but I'm always getting null values. Here's the code:

In the spec:

void "Test XML"() {
    when:
    controller.request.xml = '<book><title>My Book</title></book>'
    controller.doStuff()

    then:
    response.text == "Book title: My Book"
}

In the controller:

def doStuff() {
    request.withFormat {
        xml { render "Book title: ${request.XML?.book?.title}" }
    }
}

This is pretty similar to what the official docs describe. However, I always get:

response.text == "Book title: My Book"
|        |    |
|        |    false
|        |    7 differences (63% similarity)
|        |    Book title: (null---)
|        |    Book title: (My Book)
|        Book title: null
org.codehaus.groovy.grails.plugins.testing.GrailsMockHttpServletResponse@61a48515

when I run the test. My JSON tests that follow the same pattern are fine though.

Update

Based on this StackOverflow question, I updated the controller code to the following:

def doStuff() {
    request.withFormat {
        xml {
            def book = new XmlSlurper().parseText(request.reader.text)
            render "Book title: ${book.title}"
        }
    }
}

and it works. I could use this as a work around, of course, but this doesn't answer the unexpected behavior of request.XML. It's null, which means that the request body doesn't get parsed automatically.

Community
  • 1
  • 1
Psycho Punch
  • 6,418
  • 9
  • 53
  • 86

2 Answers2

0

It seems that your root tag is translated to request.XML, for example:

class SimpleController {

    def consume() {
        request.withFormat {
            xml {
                render "The XML Title Is ${request.XML.title}."
            }
            json {
                render "The JSON Title Is ${request.JSON.title}."
            }
        }
    }

}

@TestFor(SimpleController)
class SimpleControllerSpec extends Specification {

    void 'test consume xml'() {
        when:
        request.xml = '<book><title>The Stand</title></book>'
        controller.consume()

        then:
        response.text == 'The XML Title Is The Stand.'
    }
}

Note that I not access book.title, but title directly.

  • I don't think that's the problem. As I've mentioned, `request.XML` returns null so calling anything on it results in a `NullPointerException` (without the `?` operator). – Psycho Punch Jun 27 '14 at 05:45
  • I think your NullPointer is in the book part. have you tried my example? –  Jun 27 '14 at 19:42
  • I'm sure it's `request.XML` because the error message says the property 'title' cannot be called on null object when I make reference to `request.XML.title`. – Psycho Punch Jun 27 '14 at 20:11
  • I'm also using `request.xml` in my test class, and you're using `controller.request.xml`. Can you copy-paste my example in your project and see if it works? –  Jun 27 '14 at 20:17
  • I tried all the combinations I can think of, but nothing worked. What version of Grails are you using? – Psycho Punch Jun 28 '14 at 06:48
  • @PsychoPunch Grails v: 2.3.7 –  Jul 01 '14 at 01:02
0

In order to read mock request XML payload, a method has to be specified other than 'GET' which is default.

void "Test XML"() {
   when:
   controller.request.method='POST'
   controller.request.xml = '<book><title>My Book</title></book>'
   controller.doStuff()
   then:
   response.text == "Book title: My Book"
}