Search code examples
jmeterfunctional-testingweb-api-testingblazemeter

How to assert a JSON response which have results in random order every time in JMeter?


I am using JSON Assertion to assert if a JSON path exists. Suppose I have a JSON response of an array of 'rooms' that 'contains' an array of cabinets, just like the following example

"rooms":
[
    {
        "cabinets":
        [
            {
                "id":"HFXXXX",
                "locationid":null,
                "name":"HFXXXX",
                "type":"Hosp"
            },
            {
                "id":"HFYYYY",
                "locationid":null,
                "name":"HFYYYY",
                "type":"Hosp"
            },
            {
                "id":"HFZZZZ",
                "locationid":null,
                "name":"HFZZZZ",
                "type":"Hosp"
            }
        ],
        "hasMap":false,
        "id":"2",
        "map":
        {
            "h":null,
            "w":null,
            "x":null,
            "y":null
        },
        "name":"Fantastic Room#3"
    }
],
[
    {   "cabinets":
        [
            {
                "id":"HFBBBB",
                "locationid":null,
                "name":"HFBBBB",
                "type":"Hosp"
            }
        ],
        "hasMap":false,
        "id":"3",
        "map":
        {
            "h":null,
            "w":null,
            "x":null,
            "y":null
        },
        "name":"BallRoom #4"
    }
]

I want to Make sure that the 'id' of all the cabinets are correct, therefore I define the JSON path as rooms[*].cabinets[*].id and expect the value to be ["HFXXXX","HFYYYY","HFZZZZ","HFBBBB"]

This works perfectly except that sometimes the values are returned in a different order["HFBBBB", "HFXXX","HFYYYY","HFZZZZ"] instead of ["HFXXXX","HFYYYY","HFZZZZ","HFBBBB"], hence the assertion will fail. The problem is with the order of the returned array and not the values themselves.

Is there a way to sort the order of a response before Asserting and keep using the JSON assertion? or the only way of doing this is extracting the value i want to assert against and use it in JSR223 Assertion (groovy or javascript)? if that is the case can you show me an example of how I could do it in JSR223 plugin.


Solution

  • I would recommend using a dedicated library, for instance JSONAssert, this way you will not have to reinvent the wheel and can compare 2 JSON objects in a single line of code

    1. Download jsonassert-x.x.x.jar and put it somewhere to JMeter Classpath
    2. Download suitable version of JSON in Java library and put it to JMeter Classpath as well. If you're uncertain regarding what is "JMeter Classpath" just drop the .jars to "lib" folder of your JMeter installation
    3. Restart JMeter so it would be able to load the new libraries
    4. Add JSR223 Assertion as a child of the request which returns the above JSON
    5. Put the following code into "Script" area:

      def expected = vars.get('expected')
      def actual = prev.getResponseDataAsString()
      
      org.skyscreamer.jsonassert.JSONAssert.assertEquals(expected, actual, false)
      

      It will compare the response of the parent sampler with the contents of ${expected} JMeter Variable, the order of elements, presence of new lines, formatting do not matter, it compares only keys and values

      In case of mismatch you will have the error message stating that as the Assertion Result and the full debugging output will be available in STDOUT (console where you started JMeter from)