Set JSON element in SoapUI TestCase request using Groovy script - json

There seems to be lots of examples to do this for an XML request, the canonical form being something like:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context);
holder = groovyUtils.getXmlHolder("MyTestStep#Request" );
holder.setNodeValue( "//foo", "bar");
holder.updateProperty();
How can I do that same for a JSON request? There does not seem to be a 'getJsonHolder'.

There can be multiple ways, I belive.
Assuming there is a soapui test case with below steps
Groovy Script test step - which is going to set the json request for the next rest step
Rest Request test step
For instance, if you have full json request in string format, here is the code snippet that goes into groovy script
def stepName='restStep'
def request = context.testCase.getTestStepByName(stepName).getTestRequest()
def jsonText = '''
{
"id" : "sample id",
"name" : "sample name",
"tags" : [ "sample tags" ],
"address" : {
"street" : "sample street",
"zipcode" : "sample zipcode",
"city" : "sample city"
}
}
'''
request.setRequestContent(jsonText)
Now, try running the groovy step and see the rest test step's request body, the above request is set.
Using Property Expansion:
You may also use the Property expansion in the rest request body like shown below. Note that groovy script may not be required as we are not setting value here, instead define a custom test case level property called NAME.
{
"id": "sample id",
"name": "${#TestCase#NAME}",
"tags": ["sample tags"],
"address": {
"street": "sample street",
"zipcode": "sample zipcode",
"city": "sample city"
}
}
You may also create the dynamic request from objects as well if the data is available in object form instead of static data shown in first example.

Related

Setting a value into a json using jsonPath in karate

I have the below Json File(Test.json) read into a variable in karate
TestInput.json:
{
"firstName": "John",
"lastName" : "doe",
"age" : 26,
"address" : {
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
},
"phoneNumbers": [
{
"type" : "Mobile",
"number": "0123-4567-8888"
},
{
"type" : "home",
"number": "0123-4567-8910"
}
]
}
I intend to change the value of Mobile number within my karate code and use the Json as my request with the following lines
Karate Code:
* def reqJson = read('TestInput.json')
* karate.set('reqJson','$.phoneNumbers[?(#.type=="Mobile")].number',"999999999")
Then print reqJson
The output of the print statement doesn't have the json updated with the number for Mobile.
Alternatively, I've also used the below line to set the variable, but this hasn't worked either:
* set reqJson.phoneNumbers[?(#.type=="Mobile")].number = "99999999"
Is this possible via Karate? If Yes can someone please point me to the place where I'm going wrong or an alternative approach to achieve my scenario.
Thanks.
You can't use JsonPath to mutate. Directly access the path or use a map() operation: https://github.com/karatelabs/karate#json-transforms
This is just one example assuming the JSON is in a variable called body. Take some time to get used to JSON transforms.
* body.phoneNumbers = body.phoneNumbers.map(x => { x.number = '999'; return x })

Stop Sending Requests By Checking the Response Body in JMeter

I want to keep calling to a REST API until the Response Body contains a 100 elements.
Here is the example:
request : someurl/get/data
response :
1st API call : (2elements included)
{
"items" : [
{
"name": "abc",
"id" : "ajdiw123"
},
{
"name": "abc",
"id" : "ajdiw123345"
}
]
}
2nd API call : (4 elements)
{
"items" : [
{
"name": "abc",
"id" : "ajdiw123"
},
{
"name": "def",
"id" : "ajdiw145"
},
{
"name": "afc",
"id" : "ajdiw113"
},
{
"name": "bbc",
"id" : "ajdiw199"
}
]
}
like this response body included elements can changed. At some point it will return 100 elements with 100 different ids there. How I can identified that and stop sending the requests to the endpoint using JMeter.
It can be achieved in multiple ways depending on your test plan.
Add a JSON Extractor and a JSR223 Assertion to your request.
JSON Extractor Settings will be like:
JSR223 Assertion code will be like:
String totalIDs = vars.get("id_matchNr");
Integer result = Integer.valueOf(totalIDs);
if (result == 100){
AssertionResult.setFailure(true);
}
After that, just add a Result Status Action Handler to that request so it will stop the execution for the specific thread:
Try this:
Add a post processor in your request. A JSON Extractor to extract any of the unique array attribute say ID. JSON extractor should have a match number field set to -1 and name set as requestid and expression as $..id
Debug sampler
All this should be inside a While Controller which will have a condition
${__jexl3(${requestid_matchNr} != 100)}. "requestid_matchNr" will come from Debug Sampler response.

Attempting to retrieve a value from a JSON array in Groovy

I have a JSON object with an array (it is from the body of an HTTP response) that looks similar to the following:
{"people": [
{
"name": "john",
"city": "chicago",
"age": "22"
},
{
"name": "gary",
"city": "florida",
"age": "35"
},
{
"name": "sal",
"city": "vegas",
"age": "18"
}
]}
I'm trying to retrieve the "city" or "age" values by looking for a "name." e.g., when "name" = "sal," I'd expect to get "vegas" to be returned if I was asking for "city" or "18 if I had requested for "age." I'm attempting to do this in Groovy.
Don't even know where to start with the code. First time dealing with a JSON array. Any assistance is much appreciated.
I would recommend starting by reading Parsing and producing JSON documentation page. You will learn about the powerful groovy.json.JsonSlurper class that allows you to work with JSON documents efficiently.
When you create a JSON object representation with a method like:
def json = new JsonSlurper().parseText(rawJson)
You can access JSON document fields in the same way you access object properties. For instance, json.people will return you a list of people. Then, you can call the method like find(predicate) which returns a first result that matches the given predicate from a list. In this case, you can call something like:
def person = json.people.find { it.name == "sal" }
The it is a variable that keeps a reference to the object in the iteration process. It means that find iterates the list and searches for the first object that matches it.name == "sal".
When you find the person associated with the name, you can extract city and age fields in the same way as you would access object fields, e.g.
println person.age // prints 18
println person.city // prints vegas
Here is the full example:
import groovy.json.JsonSlurper
def rawJson = '''{"people": [
{
"name": "john",
"city": "chicago",
"age": "22"
},
{
"name": "gary",
"city": "florida",
"age": "35"
},
{
"name": "sal",
"city": "vegas",
"age": "18"
}
]}'''
def json = new JsonSlurper().parseText(rawJson) // creates JSON object
def person = json.people.find { it.name == "sal" } // finds the first person with name "sal"
assert person.city == "vegas" // calling person.city returns a city name
assert person.age == "18" // calling person.age returns age of a person
To learn more about processing JSON documents with Groovy, consider reading the documentation page I attached above. It will help you understand more complex use cases, and it will help you gain confidence in working with parsing JSON documents using Groovy. I hope it helps.

Concatenate value from the same JSON

I'm working on a configuration service in Angular 2 which simply retrieve the content of my JSON file defined above.
{
"application": {
"baseUrl": "http://localhost:1691/",
"environment": "dev"
},
"error": {
"title": "Title Error",
"description": "Error message"
}
}
I would like now, to add a properties using the baseUrl and concatenate a string after, I tried with this but it's obviously not working:
"baseApiUrl": baseUrl + "api/",
Is my requirement possible to do or have I to do it manually in my code?
My dream result would be something like this:
{
"application": {
"baseUrl": "http://localhost:1691/",
"baseApiUrl": baseUrl + "api/",
"environment": "dev"
},
"error": {
"title": "Title Error",
"description": "Error message"
}
}
My dream result would be something like this
JSON has no mechanism for referring to other parts of the structure like that. JSON is a very simple data-only format defined here.
Assuming you have that JSON as a string, you parse it, then add a property to the application object:
var configuration = JSON.parse(configurationString);
configuration.application.baseApiUrl = configuration.application.baseUrl + "api/";
Then depending on what you need to do with it, you either use configuration (the object), or turn it back into a string via JSON.stringify, or whatever else you need to do.

boto 2.8.0 and cloudseach

Hi I am trying to add documents to a cloudsearch domain as per
http://docs.pythonboto.org/en/latest/cloudsearch_tut.html#adding-documents-to-the-index
my code snppet is:
import boto
conn = boto.connect_cloudsearch(aws_access_key_id='<>',aws_secret_access_key='<>')
domain = conn.lookup('testfoo')
doc_service = domain.get_document_service()
doc_service.add(doc_id, version, data)
First I got the same requests issues
Boto CloudSearch on GAE: TypeError: request() got an unexpected keyword argument 'config'
and so I removed the config kwarg (also not sure of the consequences)
and then I get
boto.cloudsearch.document.CommitMismatchError: Incorrect number of adds returned. Commit: 1 Response: 0
My data is like this
[
{
"raw" : "whole bunch of raw text",
"title" : "My new title",
"blurb" : "A really exciting article",
"document_type" : "Tech Guide",
"url" : "http://www.foobar/7199/tech-advice"
}
]
Any help greatly appreciated
It turns out the problem is when I built up the json in data it is not json but a string. So when this produces the json being sent to the cloudsearch domain and it combines the id and "Add" operation it includes "fields": "[
{
"raw" : "whole bunch of raw text",
"title" : "My new title",
"blurb" : "A really exciting article",
"document_type" : "Tech Guide",
"url" : "http://www.foobar/7199/tech-advice"
}
]" as a string
The solution is simply data needs json encoding
doc_service.add(doc_id, version, json.loads(data))
Here just remove [] from data. Because if you have single object then you must pass it with dictionay. {}
[
{
"raw" : "whole bunch of raw text",
"title" : "My new title",
"blurb" : "A really exciting article",
"document_type" : "Tech Guide",
"url" : "http://www.foobar/7199/tech-advice"
}
]