SOAP UI JSON Groovy Scripts

Introduction

    Since soapUI allows users to add Groovy scripts in large number of places ( property expansions, setup /teardown scripts, listeners, test step, etc… ) users can use any technology to reach to the goal. Lets look at those which can make our life easier when it comes to XML parsing.

soapUI XML Support

    Old way would be soapUI way or using GroovyUtils from soapUI. Its goal is to simplify scripting and it can be instantiate from any Groovy script in soapUI, with:

def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )

where context is available in any Groovy script in soapUI. Lets look at GroovyUtils:

GroovyUtils Methods
expand(property)  
returns value of property, if there are property expansions they are expanded. 
extractErrorLineNumber(error) 
returns line number where error occurred
getProjectPath() 
 
returns path to project file           
getXml(node)
returns xml as a string from passed node
getXmlHolder(xmlPropertyOrString) 
returns XmlHolder as a result of parsing passed Xml string           
registerJdbcDriver(driver) 
register JDBC driver for use in Groovy script
setPropertyValue(testStep, property, value) 
sets a value for given test step property

This time getXmlHolder is one that does what we need. Pars a given string as XML and returns object which we can use to manipulate with it.

XmlHolder Methods
declareNamespace(prefix, uri)  declare namespace prefix and URI
getDomNode(xpath)            
returns a DOM node pointed by XPath expression 
getDomNodes(xpath)  returns an array of DOM nodes pointed by XPath expression 
getNamespaces()  returns a Map of namespaces 
getNodeValue(xpath)  returns a value of node specified by XPath expression
getNodeValues(xpath)  returns an array of values specified by XPath expression
getPrettyXml()            
returns a formatted XML 
getXml()      
returns a XML 
getXmlObject() returns a XmlBean Object 
removeDomNodes(xpath) removes a nodes specified by XPath expression 
setNodeValue(xpath, value)  set a node value  
updateProperty()  if a XmlHolder is created from test step property this updates that property 
updateProperty(prettyPrint) 

            

if a XmlHolder is created from test step property this updates that property with well formatted XML 

Few Examples

Assume you have response:

<soapenv:Envelope xmlns:soapenv=”http://schemas.xmlsoap.org/soap/envelope/&#8221; xmlns:sim=”http://www.example.org/SimpleSocialSOA/”&gt;
   <soapenv:Header/>
   <soapenv:Body>
      <sim:LoginResponse>
         <id>4456643453</id>
      </sim:LoginResponse>
   </soapenv:Body>
</soapenv:Envelope> 

For this examples I added a Properties Test Step  with property response.

1. Parsing XML

According to that to get id from response you can do:

def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder(“Properties#response”)
log.info holder.getNodeValue(“//id”)
log.info holder[‘//id’]

notice two ways to get node value with getNodeValue method and with [] operator. Difference is that getNodeValue will return first value that can be found with set XPath, while [] operator returns a array of values.
If you assume that response is like:

<soapenv:Envelope xmlns:soapenv=”http://schemas.xmlsoap.org/soap/envelope/&#8221; xmlns:sim=”http://www.example.org/SimpleSocialSOA/”&gt;
   <soapenv:Header/>
   <soapenv:Body>
      <sim:LoginResponse>
         <id>4456643453</id>
         <id>4456643452</id>
         <id>4456643451</id>
         <id>4456643450</id>
      </sim:LoginResponse>
   </soapenv:Body>
</soapenv:Envelope>

Than this script:

def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder(“Properties#response”)
log.info holder.getNodeValue(“//id”)
for( node in holder[‘//id’] )
log.info node

will produce result like this:

2. Updating XML

Response as above and we do:

def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder(“Properties#response”)
holder.setNodeValue(“//id”, “aaaaa”)
for( node in holder[‘//id’] )
log.info node
def holder2 = groovyUtils.getXmlHolder(“Properties#response”)
holder2.getNodeValue(“//id”)
for( node in holder2[‘//id’] )
log.info node

 Result is:

from this we can learn:

  • if there are several nodes as result of XPath expression only first’s node value will be changed with setNodeValue
  • setting node value is not enough to update property value, we forgot to useupdateProperty method
Correct Groovy script would be:

def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def holder = groovyUtils.getXmlHolder(“Properties#response”)
holder.setNodeValue(“//id”, “aaaaa”)
for( node in holder[‘//id’] )
log.info node
holder.updateProperty()
def holder2 = groovyUtils.getXmlHolder(“Properties#response”)
holder2.getNodeValue(“//id”)
for( node in holder2[‘//id’] )
log.info node

Instead of using:

holder.setNodeValue(“//id”, “aaaaa”)

you can use also:

holder[“//id”] = “aaaaa”

And if XmlNode is created from property as in example above useupdateProperty method to apply your changes to property or useGroovyUtils.setPropertyValue method. 

Groovy XML

There are three classes built in Groovy for processing XML: XMLParser, XMLSlurperand DOMCategory. Best practice is to use XMLSlurper in soapUI. Reason is that it have smallest memory footprint from all three. I would no go in depths for those, you can read here XML processing.
This for example:

import groovy.xml.StreamingMarkupBuilder
def response = context.testCase.testSteps[‘Properties’].properties[‘response’].value
def responseXml = new XmlSlurper().parseText(response)
responseXml.breadthFirst().each {
def v = it.toString()
if ( it.name() == ‘id’)
   it.replaceBody(“$v XX”)
}

appends ” XX” to values of all id nodes.

 

 

JSON Slurper

 

JSON stands for JavaScript Object Notation and it is lightweight data presentation format. It should be easy understandable for humans. Basically if you do not want and do not need to go in details it is same thing as XML just different packaging. As you already know or guessed when soapUI was created SOAP services were in team focus. 
    So, in soapUI you have good support for testing SOAP services and manipulating XML. What about REST and JSON?

JSON is soapUI

    Good news is that there is no much difference when working with XML and JSON in soapUI. soapUI have number of features that uses XPath to manipulate XML. Of course, you can not use XPath  expressions on JSON. Or maybe you can? In soapUI you can thanks to the fact that soapUI converts JSON to XML. That way what ever you did to assert, validate, check on etc..on XML response same thing you can do with JSON response. Only difference is that instead using Response property you have to useResponseAsXml property. ResponseAsXml is soapUI’s attempt to convert JSON to XML and all tools that you already used for XML use on JSON. 
 
 
And this is how converted XML looks likes:
 
and original JSON like this:
 
 

Nice and peachy but…

There is always one but. Problem with converting JSON to XML is that XML forces some rules that JSON do not have:
  • Names can contain letters, numbers, and other characters
  • Names cannot start with a number or punctuation character
  • Names cannot start with the letters xml (or XML, or Xml, etc)
  • Names cannot contain spaces
Here you have an issue in soapUI, since soapUI can not convert JSON to XML if any of those rules will be broken. For example look at Twitters daily trends JSON response:
 

{
   “trends”:    {
      “2012-08-29 08:20”:       [ 
                  {
            “events”: null,
            “name”: “Bizim İçin Saldır Fenerbahçe”,
            “query”: “\”Bizim İçin Saldır Fenerbahçe\””,
            “promoted_content”: null
         },
                  {
            “events”: null,
            “name”: “#RemajaIndonesiaSeptemberWish”,
            “query”: “#RemajaIndonesiaSeptemberWish”,
            “promoted_content”: null
         },
                  {
            “events”: null,
            “name”: “Most Share-Worthy Video”,
            “query”: “\”Most Share-Worthy Video\””,
            “promoted_content”: null

 
As you can notice “2012-08-29 08:20” should be node value if converted to XML but that breaks XML naming rules. So you are stuck here since there is no XML and you need to do asserting. 

Asserting JSON

    Problem is soapUI cannot convert JSON to XML because it will broke XML naming rules. You can not use XPath and XQuery assertions because of that. You can useContains and Not Contains assertions but they have very limited usage. What to do?
     You should use your favorite assertion Script Assertion with Groovy flavor. It is easy and fun, look:

import groovy.json.JsonSlurper 

def response = messageExchange.response.responseContent
def slurper = new JsonSlurper()
def json = slurper.parseText response

Script above get response content as String and pass it to JsonSlurper which parse this string and produce one big HashMap. Now working with HashMap is very easy in Groovy
     In this example ( Twitter Daily Trends ) JSON response have trends for number of dates, so if I want check if it contains trends for some particular date and time: 

assert json.trends.’2012-08-29 08:20′ != null

Notice that I had to put date under quotes since date contains white space, buttrends are good. And now I want to be sure that I have eight trends for that date and time:

assert json.trends.’2012-08-29 08:20′.size == 8   

 and 7th element name is Toby:

assert json.trends.’2012-08-29 08:20′[7].name == “Toby”

and so on…Whole script can look like this:

import groovy.json.JsonSlurper 

def response = messageExchange.response.responseContent
def slurper = new JsonSlurper()
def json = slurper.parseText response 

assert json.trends.’2012-08-29 08:20′ != null
assert json.trends.’2012-08-29 08:20′.size == 8
assert json.trends.’2012-08-29 08:20′[7].name == “Toby” 

Notice that is you have several assertions one by one in Script Assertion like on example above first assertion that fails will stop executing script, which means assertions under it ( in script ) will not be executed.
 
 

One thought on “SOAP UI JSON Groovy Scripts

Leave a comment