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.
Related
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 })
Im using the following JSON and query to calculate the array length in the JMeter json extractor.
{
"data": {
"modal": "HJ",
"technicalid": "e492fc62-a886-67a461b76de8",
"viewModel": {
"series": [
{
"name": "H_0_G_0_R_0",
"UID": "J_0_G_0_R_0",
"description": "Test1",
"type": "series",
"groups": [
{
"name": "H_0_G_0",
"UID": "G_0_G_0",
"description": "Group 1",
"type": "group"
}
],
"postProcessing": null
}
]
},
"status": "success"
},
"success": true,
"statusCode": 200,
"errorMessage": ""
}
Here is the query.
data.Model.series[0].groups.length
This is working fine in the online jsonquerytool. When I use this query in the JMeter json extractor, it is returning null. I assume this is because it is returning an integer because other similar queries which are returning strings are working fine with json extractor . How to find the array length in JMeter json extractor?
Why JSON extractor to calculate the length? You could use a post processer. Like JSR223 post processer using groovy script.
import groovy.json.*
def response = prev.responseDataAsString ;
def json = new JsonSlurper().parseText(response) ;
def sizeResultPractitioners = json.data.viewModel.series[0].groups.size();
log.info("---------->"+sizeResultPractitioners);
I tried with your JSON response payload and also tried with modified response payload,
With modified response payload,
With JSON Extractor you can provide "Match No." as -1:
and the number of matches will be available as foo_matchNr JMeter Variable:
Alternative option is going for JSON JMESPath Extractor which provides length() function so you can get the size of the array as:
length(data.viewModel.series[0].groups)
or if you prefer pipe expressions
data.viewModel.series[0].groups | length(#)
supposing the json body returned from a call contains some dynamic keys ie
{
"message": "search results matching criteria",
"permission": {
"261ef70e-0a95-4967-b078-81e657e32699": {
"device": {
"read:own": [
"*"
]
},
"account": {
"read:own": [
"*"
]
},
"user": {
"read:own": [
"*"
]
}
}
}
I can validate the json as follows easily enough although I am having a lot of trouble working out how to validate the objects BELOW the dynamic guid level of the response.
pm.test("response body to have correct items", function () {
pm.expect(jsonData.message).to.eq("search results matching criteria");
pm.expect(jsonData).to.have.property('permission');
pm.expect(jsonData.permission).to.have.property(pm.variables.get("otherUserId"));
});
Would ideally like to verify the device and account and user levels of the object.
Anyone with some tips?
I've tried a few ways to try and reference the otherUserId variable but nothing is working. It is either not resolving the variable therefore failing the test as its looking for a level in the json called otherUserId or it fails to run the test due to a syntax error.
This works:
pm.expect(jsonData.permission[pm.variables.get("otherUserId")]).to.have.property('device');
Using Apache JMeter ver 3.2 r1790745 (the latest) to test a JSON Web Service, the response is like:
[ {
"id" : 3,
"description" : "Back",
"name" : "back"
}, {
"id" : 1,
"description" : "Front",
"name" : "front"
}, {
"id" : 6,
"description" : "Left",
"name" : "left"
}]
Want to parse the above response to get all ids in one string in JSON Extractor, like
3,1,6
My JSON Path expressions is like this:
$..id
But I got only the 1st id which is 3, the same result as $.[0].id
Checking the result in a BeanShell PostProcessor.
If I go to http://jsonpath.com/
$..id does give me
[
3,
1,
6
]
If you configure your JSON Extractor like:
You will get the required value as ${foo_ALL}
I don't think using Beanshell is the best way to check JMeter Variable value, going forward I would suggest using Debug Sampler instead, see How to Debug your Apache JMeter Script for more details.
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.