How to return an jsonarray in BeanShell PostProcessor for next testcase in jmeter - jmeter

After I get a list like this:
[{
"id": "55af0d89ba411ff8b8000680",
},{
"id": "55af0d89ba411ff8b80006bc",
"object": {
"id": "55af0d89ba411ff8b80006bd",
}
}]
In the BeanShell PostProcessor I have code to return an list Id like this:
import org.json.simple.JSONObject;
import org.json.simple.JSONArray;
import org.json.simple.parser.JSONParser;
import java.util.*;
String response = prev.getResponseDataAsString();
JSONParser parser = new JSONParser();
JSONArray GroupList = (JSONArray) parser.parse(response);
Iterator i = GroupList.iterator;
JSONArray GroupIds = new JSONArray();
while (i.hasNext())
{
JSONObject objGroup = (JSONObject) i.next();
GroupIds.push(objGroup.get("id"));
}
vars.putObject("GroupIds",GroupIds);
For the next test element, I create the foreach Loop controller to loop the GroupIds, but I see in the log, it has error like this:
jmeter.util.BeanShellInterpreter: Error invoking bsh method:
eval Sourced file: inline evaluation of: ``import
org.json.simple.JSONObject; import org.json.simple.JSONArray; import
org. . . . '' : Typed variable declaration : Cannot access field:
iterator, on object:[{
"id": "55af0d89ba411ff8b8000680",
"name": "Companies",
"description": "Contacts of companies",
"type": "Group",
"created_at": "2015-07-22T03:27:05Z",
"updated_at": "2015-07-23T02:45:02Z",
"dominant_gender": "unknown",
"average_age": "?" }, {
"id": "55af0d89ba411ff8b80006bc",
"name": "Subscription",
"description": "Subscription",
"type": "Subscriptions::SubscriptionList",
"average_age": "?",
"subscription": {
"id": "55af0d89ba411ff8b80006bd",
"name": "Subcription 1",
"form_ids": ["5526430cba411ff8c30001cd"]
} }]
jmeter.extractor.BeanShellPostProcessor: Problem in BeanShell script
org.apache.jorphan.util.JMeterException: Error invoking bsh method:
eval Sourced file: inline evaluation of: ``import
org.json.simple.JSONObject; import org.json.simple.JSONArray; import
org. . . . '' : Typed variable declaration : Cannot access field:
iterator, on object:[{
"id": "55af0d89ba411ff8b8000680",
"name": "Companies",
"description": "Contacts of companies",
"type": "Group",
"created_at": "2015-07-22T03:27:05Z",
"updated_at": "2015-07-23T02:45:02Z",
"dominant_gender": "unknown",
"average_age": "?" }, {
"id": "55af0d89ba411ff8b80006bc",
"name": "Subscription",
"description": "Subscription",
"type": "Subscriptions::SubscriptionList",
"average_age": "?",
"subscription": {
"id": "55af0d89ba411ff8b80006bd",
"name": "Subcription 1",
"form_ids": ["5526430cba411ff8c30001cd"]
} }]
What is the problem?

There are few issues with your code:
Iterator i = GroupList.iterator; - parentheses are required as iterator is a method, not field.
GroupIds.push(objGroup.get("id")); - change push to add, there is no push method
Full working code:
String response = prev.getResponseDataAsString();
JSONParser parser = new JSONParser();
JSONArray GroupList = (JSONArray) parser.parse(response);
Iterator i = GroupList.iterator();
JSONArray GroupIds = new JSONArray();
while (i.hasNext()) {
JSONObject objGroup = (JSONObject) i.next();
GroupIds.add(objGroup.get("id"));
}
vars.putObject("GroupIds", GroupIds);
By the way, it isn't very recommended to use Beanshell for under high load as it is not very efficient. For one thread it is OK, but when it comes to immense load - it may become performance bottleneck and may ruin your test. If it is the case - consider switching to JSR223 PostProcessor and "groovy" language instead.
A very little change will be required:
adding groovy-all.jar to JMeter's /lib folder
substitute all Beanshell test elements to JSR223 with "groovy" engine
See Beanshell vs JSR223 vs Java JMeter Scripting: The Performance-Off You've Been Waiting For! article for detailed installation instructions, scripting tips and tricks and different scripting engines performance benchmark.
UPDATE - generate variables for ForEach Controller:
import org.json.simple.parser.JSONParser;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
String response = prev.getResponseDataAsString();
JSONParser parser = new JSONParser();
JSONArray GroupList = (JSONArray) parser.parse(response);
for (int i = 0; i < GroupList.size(); i++) {
JSONObject objGroup = (JSONObject) GroupList.get(i);
vars.put("Group_" + i, objGroup.get("id"));
}
Then add a ForEach Controller and configure it as follows:
Input variable prefix: Group
Start index: -1
Output variable name: CURRENT_GROUP
Add "_" before number - check the box
Use ${CURRENT_GROUP} where required

Related

Need to form custom request in jmeter

I am in need to create a custom request in jmeter which looks like the below format:
{
"items": [
{
"id": "1",
"productId": 1234
}
{
"id": "2",
"productId": 1218
}
....
}
Here I have to generate some random number in between 10-15 and create the id blocks(based on the random number).
Could someone please help how can I form the request accordingly and achieve this in jmeter.
Thanks in advance.
Add JSR223 PreProcessor as a child of the request which need to send this generated value
Put the following code into "Script" area
import groovy.json.JsonBuilder
import org.apache.commons.lang3.RandomUtils
def items = []
def itemsNo = RandomUtils.nextInt(10, 16)
1.upto(itemsNo) { id ->
def productId = RandomUtils.nextInt(1111, 10000)
def item = [:]
item.put('id', id as String)
item.put('productId', productId)
items.add(item)
}
def payload = new JsonBuilder([items: items]).toPrettyString()
vars.put('payload',payload)
Use ${payload} JMeter Variable where you need to refer the generated JSON
Demo:
More information:
Apache Groovy - Parsing and producing JSON
Apache Groovy - Why and How You Should Use It

validate response using jsr223 assertion

I have passed chgId as parameter in the get HTTP request.
https://*****?chgId=405
My api response is coming as -
{
"response": {
"data": [
{
"tid": 3697,
"chgId": 405,
"amount": 8.5,
"Currency": "USD",
},
{
"tid": 3698,
"chgId": 405,
"amount": 3.33,
"Currency": "USD",
}
]
}
}
Now from the response I want to validate in JSR223 assertion that the response is correct based on the chgId field. That means in both 'data' array "chgId": 405 text should come.
Can anyone suggest?
You could do something like:
def params = org.apache.http.client.utils.URLEncodedUtils.parse(prev.getURL().toURI(), 'UTF-8')
def expected = params.find { 'chgId' }.value as int
def actual1 = new groovy.json.JsonSlurper().parse(prev.getResponseData()).response.data[0].chgId
def actual2 = new groovy.json.JsonSlurper().parse(prev.getResponseData()).response.data[1].chgId
def success = (expected == actual1 && expected == actual2)
if (!success) {
AssertionResult.setFailure(true)
AssertionResult.setFailureMessage('chgId mismatch')
}
where prev stands for previous SampleResult
More information:
URLEncodedUtils JavaDoc
JsonSlurper
Apache Groovy - Parsing and producing JSON
Scripting JMeter Assertions in Groovy - A Tutorial

JGraphT: How to use JSONImporter to Import my DirectedMultigraph with Labeled Edges

I have created a custom edge class as defined here. The only change I made was a No Arg constructor in order to get the import code below to run. I have successfully generated a DirectedMultigraph via the JSONExporter class and now want to take that exported JSON and re-import it via the JSONImporter class.
I'm having trouble doing this and retaining my edge labels due to my limited understanding of how to build the EdgeProvider required for my JSONImporter constructor.
This is the JSON I'm trying to import:
{
"edges": [
{
"id": "{shipmentNumber:12345}",
"source": "DEHAM",
"target": "USNYC"
}
],
"nodes": [
{
"id": "DEHAM"
},
{
"id": "USNYC"
}
],
"creator": "JGraphT JSON Exporter",
"version": "1"
}
This is the code that I have so far:
Graph<String, RelationshipEdge> graph = new DirectedMultigraph<>(SupplierUtil.createStringSupplier(), SupplierUtil.createSupplier(RelationshipEdge.class), false);
VertexProvider<String> vertexProvider = (label, attributes) -> label;
EdgeProvider<String, RelationshipEdge> edgeProvider =
(from, to, label, attributes) -> graph.getEdgeSupplier().get();
JSONImporter<String, RelationshipEdge> importer = new JSONImporter<>(vertexProvider, edgeProvider);
importer.importGraph(graph, new StringReader([inputJSON]);
I know the problem is the EdgeProvider assignment because I don't know how to pass the argument constructor for the RelationshipEdge class which is where the actual label is set. If I could figure out how to call the argument constructor of the RelationshipEdge class then I think that would solve my problem.
FYI, this is my JSONExporter Code:
ComponentNameProvider<String> vertexIdProvider = name -> name;
ComponentNameProvider<RelationshipEdge> edgeLabelProvider = component -> component.getLabel();
ComponentAttributeProvider<String> vertexAttributeProvider = component -> new HashMap<>();
ComponentAttributeProvider<RelationshipEdge> edgeAttributeProvider = component -> new HashMap<>();
GraphExporter<String, RelationshipEdge> jsonExporter = new JSONExporter<>(vertexIdProvider, vertexAttributeProvider, edgeLabelProvider, edgeAttributeProvider);
StringWriter writer = new StringWriter();
jsonExporter.exportGraph(graph, writer);
System.out.println(writer.toString());
The following JSON is exported (with the label/id missing):
{
"creator": "JGraphT JSON Exporter",
"version": "1",
"nodes": [
{
"id": "DEHAM"
},
{
"id": "USNYC"
}
],
"edges": [
{
"source": "DEHAM",
"target": "USNYC"
}
]
}
Since your graph is using the SupplierUtil factory methods, the graph importer will use no-arg constructors as it visits/parses the json file, iterates over all the nodes/edges in the file and creates instances for them. In order to set your node/edge attributes during import you need to provide appropriate Vertex/Edge Attribute Consumers to the importer. Additionally, your node/edge classes need methods to access/modify their attributes:
JSONImporter<String, RelationshipEdge> importer = new JSONImporter<>(vertexProvider, edgeProvider);
importer.addEdgeAttributeConsumer((edgeField, value) -> {
// edgeField: Pair<Edge, String> / Edge instance, field name
// value: instance of org.jgrapht.nio.Attribute / getValue(); getType();
RelationshipEdge = edgeField.getFirst();
e.setLabel(value.getValue()); // Note that since you only have one field I am not finding the
// correct setter. I don't like reflection so I would probably
// add a 'setField(name, value)' method to my edge/node implementation.
});
To persist your graph, the idea is the same. But in this case you need Vertex/Edge AttributeProviders (You added them but they always returned empty maps):
GraphExporter<String, RelationshipEdge> jsonExporter = new JSONExporter<>();
exporter.setEdgeAttributeProvider(e -> {
Map<String, Attribute> attribs = new HashMap<>();
attribs.put("label", new DefaultAttribute<String>(e.getLabel(), AttributeType.STRING));
return attribs;
});

How to remove unwanted keys from rest-assured response object and assert remaining object data with constant variable having json string using java

In rest-assured test cases I am getting response as mentioned, where I want to remove keys such as "updated_at", "deleted_at", "created_at" and "notice" and then assert this response object with expected json string constant which contains 'settings'
{
"notice": "The Settings are updated successfully.",
"settings": {
"push_notification": {
"enabled": true,
"credentials": [{
"key": "value"
}],
"service_name": "API Testing"
},
"created_at": "2019-05-04T14:52:32.773Z",
"deleted_at": "false",
"updated_at": "2019-05-07T11:23:22.781Z"
}
}
For given response the expected json string is...
public static String SETTING_EXPECTED = "{\"push_notification\": {\"enabled\": true, \"credentials\": [{\"key\": \"value\"}], \"service_name\": \"API Testing\"}}"
Please help me with creating a common method using java which can be reuse for response assertions in all the test cases.
To delete keys from response you can use below code I am using jayway jsonpath library, you need to pass Json Response and field name jsonPath, in case your it will be "$.settings.created_at" :
public String deleteFieldNameFromResponse(String jsonResponse, String fieldToDelete)
throws ParseException, FileNotFoundException, IOException {
Object obj = null;
JSONParser parser = new JSONParser();
JsonPath jsonPath = null;
DocumentContext docCtx = null;
obj = parser.parse(jsonResponse);
docCtx = JsonPath.parse(obj);
docCtx.delete(fieldToDelete);
jsonPath = JsonPath.compile("$");
return docCtx.read(jsonPath).toString();
}

Consuming REST Service in Spring

I'm frightfully new to Spring and Java but I'm trying to consume some code for some rule validations in Easy Rules but I can't quite figure it out.
#RequestMapping(method = {RequestMethod.GET}, value = "author/field", produces= MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody ResponseEntity<Enum> getField(#RequestParam(value="field", required=true) String field){
Enum enum = mongoService.findByField(field);
if(enum == null){
return new ResponseEntity<Enum>(HttpStatus.NO_CONTENT);
}else{
return new ResponseEntity<Enum>(enum,HttpStatus.OK);
}
}
So I'm trying something like:
import com.mongoservice.Enum
import com.mongoservice.Enums
RestTemplate restTemplate = new RestTemplate();
String uri = "http://localhost:9000";
//This is my confusion
List<Enums> response = restTemplate.getForObject(uri +
"/author/field?={field}", Enum.class,"a").getEnums();
String value = response.getValue().toString().trim();
//this is the record i'm checking against that is pulling a specific string value and what i'm expecting
String record = "a";
return (value == record);
The JSON data I'm trying to pull back is modeled like this but I need to validate to make sure that record equals one of the values from enums[] json array
{
"field": "a",
"descriptor": "blah",
"enums": [
{
"value": "h",
"description": "blah"
},
{
"value": "e",
"description": "blah"
},
{
"value": "l",
"description": "blah"
},
{
"value": "p",
"description": "blah"
}
]
}
What is the problem that you are seeing is it just not matching? If so it could be because you are using == instead of String.equals. Try modifying your code to:
return record.equals(value);
See Java String.equals versus == for more.
Can you change String uri = "http://localhost:9000"
and missed the path variable name field it should be like author/field?field={field} as per your controller description.

Resources