Tuesday, June 1, 2010

Grails Wizardry: Mocking all your web services with Grails

Background

At work, we are using EC2 to run capacity tests on our environment, which would normally be pretty trivial, but we are a big SAAS shop with tons and tons of endpoints internally.  Without setting up EVERYTHING in the cloud, we can't really run our tests...or can we?  We would love to use Amazon VPC for EC2, but it requires a fair amount of intervention from your network team.  That will be a great alternative down the road - being able to point back into the internal network to access machines rather than deploying them in the cloud.  So, plan b - Using grails, I was able to mock every single .NET service that our application talks to in about three hours.  Here are the details:

We use SOAP services that return some XML, I simply used Fiddler to see what responses are sent back over the wire for each service, and I was ready to rock.  There are two main pieces to the puzzle:

MarkupBuilders


Generating XML is almost too easy in Groovy.  Using the instructions here, I was able to write some code that spits out some xml based on info passed in.  For instance this sample Grails controller will take a login and company and return an XML document with a user id and company id:


import groovy.xml.MarkupBuilder

class UserController {

  /**
  * /MyService/users/getuser?login=myuser&company=mycompany
  */
  def returnUser = {

        def user = params.login
        def comp = params.company

        def writer = new StringWriter()
        def xml = getXMLBuilder( writer )

        xml.'user'('xmlns:xsi': getNsXsi(), 'xmlns:xsd': getXsd(), 'xmlns': getXmlNs() ) {
          userId( "${comp }@${user}" )
          compId( "${comp}@compId" )
        }

        render( text: writer.toString(), contentType:"text/xml", encoding:"UTF-8" )
  }

  def getXMLBuilder( StringWriter writer ) {

        writer.append(  "" )

        return new MarkupBuilder( writer )
  }

  def getNsXsi() {
        return "http://www.w3.org/2001/XMLSchema-instance"
  }

  def getXsd() {
        return "http://www.w3.org/2001/XMLSchema"
  }

  def getXmlNs() {
        return "http://yourcompany.com/UserStuff/2009/11/01"
  }
}


Now that you have defined your controller, you need to make it so your application can make its normal request to the url it has configured but still get to your controller.  That's where the URLMappings.groovy class comes in:

UrlMappings

The UrlMappings file already exists by default when creating a project.  This file is built to map external urls to your controllers - you can use it to create nice shiny RESTful URLs, or just to do some utilitarian mappings for backwards compatibility, etc.  Obviously not every project's requirements map to the grails conventions on how urls map to controllers.  To add access to your controller from a different url, you just need to add the following snippet - this will allow Grails to map your request from something like

/MyService/users/getuser?login=me&company=acme

to

/user?login=me&company=acme 


    "/MyService/users/getuser" {
          controller = "user"
          action = "returnUser"
    }


More information can be found at this link.

At this point, you have a service running that will return the valid XML for your service, and will respond to a call at a URL that doesn't actually match.  Now you can rinse and repeat for each service that you need to mock out.  Happy Grailing!
blog comments powered by Disqus