views:

529

answers:

2

I have a put request that I am trying to unit test for creating a user object.

Unit Test:

    void testPUTXMLResponse() { 
 def mockUser = new User(username:"fred", password:User.encrypt("letmein"), firstName:"Fred", lastName:"Flintstone", middleName:"T", phone:"555-555-5555", email:'[email protected]', activationDate:new Date(), logonFailureCount:0)
 mockDomain(User, [mockUser])

 def mockUserXML = mockUser as XML
 mockRequest.method = 'PUT'
 mockRequest.contentType = 'text/xml'
 mockRequest.format = 'xml'
 mockRequest.content = mockUserXML.toString().getBytes()

 controller.create()

 def updatedUser = XML.parse(mockResponse.contentAsString)
 assert updatedUser.id == 1
}

Controller Action:

    def create = {
 println request.xml
 def user = new User(params.user)
 if(!user.hasErrors() && user.save()) {
  println user.id
  withFormat {
   html { /*render(view:"show", [user:user])*/ }
   xml { render user as XML }
   json { render user as JSON }
  }
 } else {
  println user.errors
  withFormat {
   html { /*render(view:"create", [user:user])*/ }
   xml { render user.errors as XML }
   json { render user.errors as JSON }
  }
 }
}

For some reason the params map is null when the controller action is executed. I have a very similar unit test for POST requests and it works just fine.

A: 

Grails natively supports REST, so Grails enforces the HTTP specification for PUT and POST. One of the rules for PUT is that it needs a full URL, including the ID of the object that is being acted on. In this case, when creating a new User the ID isn't known until after the request. Therefore, the full URL isn't known and the PUT request fails. POST does not have this restriction. For a more in-depth explanation of PUT and POST, see http://jcalcote.wordpress.com/2008/10/16/put-or-post-the-rest-of-the-story/

John Kinzie
A: 

It seems that the issue you described is caused by the difference in the Tomcat handles PUT vs. POST requests (see here). Switch out the tomcat plugin for the jetty and your example should work.

BungleFeet