9

I'm writing a Grails 2.2.1 integration test using the Spock plugin, in which I am trying to post two sets of data to the same controller endpoint:

when: "The user adds this product to the inventory"
def postData = [productId: 123]
controller.request.JSON = postData
controller.addToInventory()

and: "Then they add another"
def secondPostData = [productId: 456]
controller.request.JSON = secondPostData
controller.addToInventory()

then: "The size of the inventory should be 2"
new JSONObject( controller.response.contentAsString ).inventorySize == 2

The problem I am seeing is that the same JSON is submitted to addToInventory() for both requests.

This StackOverflow question suggests calling controller.request.reset(), but this did not work (No signature of method: org.codehaus.groovy.grails.plugins.testing.GrailsMockHttpServletRequest.reset()).

Is what I am attempting possible?

Community
  • 1
  • 1
  • One important thing, to note is the use of controller.request.JSON to pass data to the post method! It was really hard to find. – Neoecos Oct 22 '14 at 03:48

3 Answers3

6

"Where:" can be used to perform data driven testing in spock testing framework. Try, using the following example:

when: "The user adds this product to the inventory"

controller.params.JSON = [productId:productId]
controller.addToInventory()

then: "The size of the inventory should be 2"
new JSONObject( controller.response.contentAsString ).inventorySize == 2

where:

ID|productId
1|123
2|456

Hope that helps!!!

Anuj Aneja
  • 1,323
  • 11
  • 13
  • 2
    Thanks Anuj, I have refactored the test to look like your example above. There was also a problem with how I was assigning parameters to the request, so the line `controller.request.JSON = [productId:productId]` is now `controller.params.JSON = [productId:productId]`. – Bryan O'Sullivan Sep 12 '13 at 14:45
3

There is actually another way. Insert:

GrailsWebUtil.bindMockWebRequest()

at the start of your second test. This will effectively create a new ServletContext, a new MockHttpServletRequest, a new MockHttpServletResponse, and then bind all three into the current thread.

mmigdol
  • 2,023
  • 1
  • 18
  • 20
0

While Anuj us correct that where clauses should be used to keep tests clean, there are times when a test needs to run more than one request. In my case I wanted to test that when it recieved 2 repeat POSTS, the 2nd one was rejected correctly.

I found that resetting the response did what I needed:

controller.response.reset()

To clear out the response.

doelleri
  • 19,232
  • 5
  • 61
  • 65
adeady
  • 467
  • 1
  • 4
  • 19