Get a parent value based on child value in SoapUI - json

In the response Json, getting an array list of items as shown.

What you see in the question is not xml, it is a json string. So, xpath does not work.
For your request test step, you can add the Script Assertion as shown below:
//Check the response
assert context.response, 'Response is empty or null'
//Expected subscription id, change it if needed
def expectedSubscriptionId = '2c92c0f95ae1445b015af2320235689f'
def parsedJson = new groovy.json.JsonSlurper().parseText(json)
def ids = [] as Set
parsedJson.each { item ->
item.amendments.each { amendment ->
if (amendment.subscriptionId == expectedSubscriptionId ) {
ids << item.id
}
}
}
assert ids.size(), "id's are not found in the response for matching subscription"
log.info "Matching id's are : ${ids}"
You may quickly try online Demo

Related

Json Assertion - Error Assertion failure message: Value expected to match regexp

Doing REST API Testing using Jmeter. when I am Using JSON Path Tester in HTTP Response and provided JSON Path Expression as $..name. Getting following matches
Done,
Won't Do,
Duplicate,
Cannot Reproduce
But when I place the same JSON expression and Result in JSON Assertion, getting the error:-
Assertion error: false
Assertion failure: true
Assertion failure message: Value expected to match regexp '"Done","Won't Do","Duplicate","Cannot Reproduce"', but it did not match: '["Done","Won't Do","Duplicate","Cannot Reproduce"]'
To match multiple values
Extract all the matching values from JSON Response using JSON Extractor
Use JSR223 Assertion with following code:
int nameLength = Integer.parseInt(vars.get("Name_matchNr"));
String[] responseArray = new String[nameLength];
for (int i = 0; i < nameLength; i++) {
responseArray[i] = vars.get("Name_"+(i+1));
}
boolean test1 = Arrays.asList(responseArray).contains("Done");
boolean test2 = Arrays.asList(responseArray).contains("Won't Do");
boolean test3 = Arrays.asList(responseArray).contains("Duplicate");
boolean test4 = Arrays.asList(responseArray).contains("Cannot Reproduce");
if (test1 == false) {
AssertionResult.setFailureMessage("Done not present in Response");
AssertionResult.setFailure(true);
}
if (test2 == false) {
AssertionResult.setFailureMessage("Won't Do not present in Response");
AssertionResult.setFailure(true);
}
if (test3 == false) {
AssertionResult.setFailureMessage("Duplicate not present in Response");
AssertionResult.setFailure(true);
}
if (test4 == false) {
AssertionResult.setFailureMessage("Cannot Reproduce not present in Response");
AssertionResult.setFailure(true);
}
To match single value
Use JSON Extractor to extract the values
Use JSON Assertion to Assert the values. In Expected Value section enter any single value : "Done/Won't Do/Duplicate/Cannot Reproduce"
If this is really what you're trying to achieve, consider the following JSON Assertion configuration:
Just in case "Expected Value" textual representation:
["Done","Won't Do","Duplicate","Cannot Reproduce"]
However be informed that this form of assertion will be fragile and sensitive to any JSON changes, i.e. if the order of matches will not be the same - the assertion will fail. So I would rather recommend using one of the approaches described in The Easiest Way To Compare REST API Responses Using JMeter article.

Groovy - JSONSlurper parsing json

I have problem with my SoapUI Groovy script. I have following json (simplified):
{
"data":{
"XXX":[...]
"YYY":[...]
},
"next":"ffawef234fava23r"
}
I have values of XXX and YYY in my previously TestStep as request parameters and I extract it properly as list of string, but my problem is that I need to extract content of data.XXX and data.YYY, but when I want to do this in loop I always get null. My code:
def content = new JsonSlurper().parseText(response)
def ids = extracted_ids.split(';') //List of IDs in response above {XXX,YYY}
for (id in ids){
log.info id // XXX
log.info content.data.'XXX' //this works
log.info content.data.id //this not
}
Is there any option to pass this "id" in loop to content.data.{id} to get any content instead of null
Kind Regards
You just need to do
log.info content.data."$id"

Script Assertion to get token and set it as http header to the next test step

How to write a script(assertion) in order to get the randomAccessToken as output from the given code.The code is in json format.
{
"status": "Success",
"code": 1000,
"message": "Random access token generated",
"randomAccessToken": "ef12286f-3263-4c3b-949a-3a43497254e2-20162124112138-1722093936686484240"
}
UPDATE from comment:
I need the header name as "randomAccesstoken" but for the next TestStep because to run that I need this info.
Have grrovy script assertion and paste the below code.
import groovy.json.JsonSlurper
def jsponresponse = messageExchange.responseContent
def jsonSlurper = new JsonSlurper()
jsonParsed = jsonSlurper.parseText(jsponresponse)
actualValue = jsonParsed.randomAccessToken
log.info actualValue
assert 12 < actualValue.length
//here you need to use groovy regx or string length grater than as assert i used srting length
Hope this helps!! dont forget to click answered.. if it didn't work provide your finding we solve.
Now the refined script assertion would do ,store the randomacesskey in to a property ,that can be used in next HTTP REQUEST headers
import groovy.json.JsonSlurper
def jsponresponse = messageExchange.responseContent
def jsonSlurper = new JsonSlurper()
jsonParsed = jsonSlurper.parseText(jsponresponse)
actualValue = jsonParsed.randomAccessToken
log.info actualValue
assert 12 < actualValue.length
context.testCase.testSteps["requestProps"].setPropertyValue( "Tokenkey", actualValue )
what does it mean? the new line
context.testCase.testSteps["requestProps"].setPropertyValue( "Tokenkey", actualValue )
In order the above line to get execute , you need to add testStep properties and rename it as "requestProps" and add a entry "Tokenkey"
by the time the script assertion excuted successfully , script have extracted and stored randomAccessToken value in to Tokenkey refernce , for cross reference open properties step after the execution of first request successfully and you see a value that got extracted from randomAccessToken
i.e., you see this after executing the firt request,
requestProps
Tokenkey = yettqutt-ajsfugau-uyatwdua
Now in the another any request of the same test case which requires this extracted Randomaccess token in header section ?
How to do that ?
open that httpRequest -->headers--> add an entry that server accepts
if in your case server accepts name of the randomaccess key is "access-key"
then an add entry
access-key = ${requestProps#Tokenkey}
now fire the second or 3rd nth request you have set this header parameter in the request it will go through.
Here you go with the script assertion, comments in line explaining what it is doing in the each statement:
This script will fetch the value from json and set it has http header to the next test step automatically.
UPDATE from the comment: to add the header to next request
Make sure you have the right value for headerName variable, by default I have set it to randomAccesstoken as requested.
import net.sf.json.groovy.JsonSlurper
//Please edit the header name you wanted
def headerName = 'randomAccesstoken'
// get the next test step name automatically, set the name if you want it for different step which is not the immediate next step
def nStepName = context.testCase.testStepList[context.currentStepIndex + 1].name
//a method which sets the headers
def setHttpHeaders(String nextStepName, def headers) {
def nextRequest = context.testCase.testSteps[nextStepName].httpRequest
def existingHeaders = nextRequest.requestHeaders
headers.each {
existingHeaders[it.key] = it.value
}
nextRequest.requestHeaders = existingHeaders
}
//create parser and pass the response that you received
def json = new JsonSlurper().parseText(messageExchange.responseContent)
//read the token
def token = json.randomAccessToken
//assert the value of token if null or empty
assert token, "Response does not contain Token or null"
//UPDATE from the comment to add the header to next request
if (token) {
log.info "next test step name is : ${nStepName}"
def headerValue = [(token)]
def headers = [(headerName) : (headerValue)]
setHttpHeaders(nStepName, headers)
}

How do I get Value from a converted String

I have this code:
"response=3&responsetext=Duplicate transaction REFID:3154223053&authcode=&transactionid=&avsresponse=&cvvresponse=&orderid=&type=auth&response_code=300"
I tried converting it into json format using this code:
def converted = "{\"" + resp.data.toString()
.replaceAll('=','\":\"')
.replaceAll('&','\",\"') + "\"}"
it returns the valid json format though I want to get a specific value from that string I tried doing:
println converted.responsetext.toString()
it has an error saying
No such property: responsetext for class: java.lang.String
You can convert request parameters to Map and if required to json string as below:
String str = "response=3&responsetext=Duplicate transaction REFID:3154223053&authcode=&transactionid=&avsresponse=&cvvresponse=&orderid=&type=auth&response_code=300"
def map = str.tokenize(/&/).collectEntries {
def entity = it.tokenize(/=/)
[ entity[0], entity[1] ]
}
assert map.responsetext == "Duplicate transaction REFID:3154223053"
// Json
println new groovy.json.JsonBuilder( map ).toPrettyString()
If you want to go ahead from what you have right now instead, then below implementation should be sufficient:
def items = new groovy.json.JsonSlurper().parseText( converted )
assert items.responsetext == "Duplicate transaction REFID:3154223053"

How do I use groovy to create a json array?

Example (thought of) taken from groovy ws-lite git hub project.
Say I have the following code block to send a RESTful post request:
void 'Holiday Service get holidays by country, year and month'() {
given:
def client = new RESTClient('http://www.holidaywebservice.com/HolidayService_v2/HolidayService2.asmx')
when:
def response = client.post(path: '/GetHolidaysForMonth') {
type ContentType.JSON
json files: ['spec_test.txt':[content: "2014-12-12"]]
}
then:
200 == response.statusCode
'text/xml' == response.contentType
'Christmas' == response.xml
.Holiday
.find { it.HolidayCode.text() == 'CHRISTMAS-ACTUAL'}
.Descriptor.text()
}
Here is what's generated in the request body:
{"files":{"spec_test.txt":{"content":"2014-12-12"}}}
How can I change the code to generate this json array instead:
[{"files":{"spec_test.txt":{"content":"2014-12-12"}}}]
Note the following code can do the trick:
def sampleRequest = '[{"files":{"spec_test.txt":{"content":"2014-12-12"}}}]'
def jsonArray = new JsonSlurper().parseText( sampleRequest )
void 'Holiday Service get holidays by country, year and month'() {
given:
def client = new RESTClient('http://www.holidaywebservice.com/HolidayService_v2/HolidayService2.asmx')
when:
def response = client.post(path: '/GetHolidaysForMonth') {
type ContentType.JSON
json jsonArray
}
then:
200 == response.statusCode
'text/xml' == response.contentType
'Christmas' == response.xml
.Holiday
.find { it.HolidayCode.text() == 'CHRISTMAS-ACTUAL'}
.Descriptor.text()
}
But I want to know if there is another way to do this?
As far as I understood well You just need to replace the following line:
files: ['spec_test.txt':[content: "2014-12-12"]]
with this one:
[[files: ['spec_test.txt':[content: "2014-12-12"]]]]
It just passed a list instead of map to json key, but double square brackets are needed because one pair will be used to indicate a map and the second one to create a list.