Configurable option for generating body content in Post requests
- 7 years ago
Hi,
What I did:
I have a Properties block that contains a json Keynames as key in the block, and json paths as values. E.g.
key 'someKey', value 'a.b.c'
This Properties block is placed in a testcase named 'templates'
This properties block is used to store structure information about the body and has the type of request in it's name, e.g. PathsForSomeMessage.
The testcase also contains a template Properties block that contains the same keys as in the other properties block. This is to be used for filling in specific values. The name also contains a reference to the type of request to be used, say ValuesForSomeMessage. E.g.
key 'someKey', value empty
In each testcase where you want to use the type of request you clone the values Properties block and fill in the wanted values, say 'someValue'.
You also create/clone a DataGen teststep with a property for creation of body of wanted message, e.g. 'create somemessag body'. In this you call an external groovy script with the name of the messagetype as input.
That will look like
return com.myproject.soapui.common.JsonBodyContentGenerator.getBodyContent(testRunner,context,log, 'SomeMessage')
In the request of your testcase you fill in the body of the teststep a reference to the DataGen step, '${GenerateParameters#create somemessage body}'
The body generated will look like this
{"a":{"b":{"c":"someValue"}}}
Now if the needed structure of the body content of the body changes in the body structure, say for instance that "c" has to be in node "d" instead of node "b", all you have to do is change the path for key "c" to "a.d.c" in Property block PathsForSomeMessagePathsForSomeMessage. This will change the structure for all messages of SomeMessage, leaving the used value intact. So one generated body will look like: {"a":{"d":{"c":"someValue"}}}
The external Grooovy script I have written:
package com.myproject.soapui.common; import groovy.json.* public class JsonBodyContentGenerator { static getBodyContent(def testRunner, def context, def log, String requestName) { String templateName = 'PropertiesPathsFor' + requestName String valuesName = 'PropertiesValuesFor' + requestName def pathProperties = testRunner.testCase.testSuite.getTestCaseByName("templates").getTestStepByName(templateName) def valueProperties = testRunner.testCase.getTestStepByName(valuesName) def body = [:] for (prop in valueProperties.propertyNames) { def path = 'body.' + pathProperties.properties[prop].value def value = valueProperties.properties[prop].value pathFinder(body, path, value) } return JsonOutput.toJson(body) } static pathFinder(int i, Map structure, String[] paths, String value) { def splitBracket = paths[i+1].split('\\[') def nextPath = splitBracket[0] if (i == (paths.size() - 2)) { if (splitBracket.size() > 1) { def arrayToSet = structure.get(nextPath) if (arrayToSet != null) { arrayToSet.add(value) } else { arrayToSet = [ value ] } structure.put(nextPath, arrayToSet) } else { structure.put(nextPath, value) } } else { if (structure.containsKey(paths[i+1])) { Map mapForKeys = structure.get(paths[i+1]) pathFinder(++i, mapForKeys, paths, value) } else { def keyForMap = nextPath if (splitBracket.size() > 1) { def mapIntoArray = [:] pathFinder(0,mapIntoArray, paths[(i+1)..(paths.size()-1)] as String[], value) def arrayToSet = structure.get(nextPath) if (arrayToSet != null) { arrayToSet.add(mapIntoArray) } else { arrayToSet = [ mapIntoArray ] } structure.put(nextPath, arrayToSet) } else { Map mapForKeys = [:] structure.put(keyForMap, mapForKeys) pathFinder(++i, mapForKeys, paths, value) } } } } static pathFinder(Map structure, String path, String value) { def pathSteps = path.split('\\.') pathFinder(0,structure,pathSteps,value) } }