Forum Discussion

emmanuelkatto23's avatar
emmanuelkatto23
New Contributor
6 months ago

Testing RESTful APIs with complex request - Emmanuel Katto Uganda

Hi All, I am Emmanuel Katto. We're developing a web application that consumes a RESTful API to retrieve and update data. The API uses JSON payload to send and receive data, and the payload can contain complex structures such as nested arrays and objects. We're struggling to effectively test these APIs using SoapUI or ReadyAPI, and would like to know if there are any best practices or techniques that can help us overcome this challenge. Specifically, I want to know how can we effectively use XPath or JSONPath expressions to navigate and assert the contents of complex JSON payloads?

Thanks!

Emmanuel Katto

 

  • Hello emmanuelkatto23 

    I have a technique to share but it is not specific to XPath or JSONPath... 

    The technique I employ is to use JsonSlurper (https://docs.groovy-lang.org/latest/html/gapi/groovy/json/JsonSlurper.html).  It is very efficient and has allowed me to interrogate every complex JSON structure that I have explored.  I only use a groovy test step to make my own assertions from other test step results that contain the actual invoke of an API from an 'HTTP Request' test step and not a 'REST Request' test step.  I prefer HTTP Request over Rest Request so that I don't have to import an API to use it (less baggage in my mind).

    Sample stand alone JsonSlurper code with assert to copy/paste/run into groovy test step...

    import groovy.json.JsonSlurper;
    
    log.info 'Test Step "' + testRunner.runContext.currentStep.name + '" start...';
    log.info "";
    
    def String jsonStr = """
    {
      "step_list": [
        {
          "end_date": "2035-09-01T00:00:00",
          "payments": 12,
          "sequence": 1
        },
        {
          "end_date": "2035-09-01T00:00:00",
          "payments": 67,
          "sequence": 2
        }
      ]
    }
    """;
    
    def jsonSlurper = new JsonSlurper();
    def jsonObj = jsonSlurper.parseText(jsonStr);  
    log.info "jsonObj=$jsonObj";
    
    def expectedSize = 2;
    assert jsonObj.step_list.size() == expectedSize, "Expected step_list size to be $expectedSize but it is = ${jsonObj.step_list.size()}";
    
    log.info "jsonObj.step_list.first()=${jsonObj.step_list.first()}";
    log.info "jsonObj.step_list.last()=${jsonObj.step_list.last()}";
    
    def datePattern = "yyyy-MM-dd";
    jsonObj.step_list.each { step ->
       log.info "";
       log.info "step=${step}";
    
       def stepDate = Date.parse(datePattern, step.end_date);
       log.info "stepDate=${stepDate}";
    
       Date lowDate = new Date("08/15/2020");
       Date highDate = new Date("10/15/2040");
       def nowDate = new Date();
       assert stepDate > lowDate, "Expected the step date to be greater than $lowDate but it is $stepDate";
       assert stepDate < highDate, "Expected the step date to be less than $highDate but it is $stepDate";
       assert stepDate > nowDate, "Expected the step date to be greater than today but it is $stepDate";
    
       def expectedPaymentMinimum = 10;
       assert step.payments > expectedPaymentMinimum , "Expected the step payments to be greater than $expectedPaymentMinimum but it is ${step.payments}";
       
       if (step == jsonObj.step_list.first()) {
          log.info "step.sequence=${step.sequence}";
          def expectedFirstSequence = 1;
          assert step.sequence == expectedFirstSequence, "Expected the first step sequence to be $expectedFirstSequence but it is = ${step.sequence}";
       };
       if (step == jsonObj.step_list.last()) {
          log.info "step.sequence=${step.sequence}";
          def expectedLastSequence = 2;
          assert step.sequence == expectedLastSequence, "Expected the last step sequence to be $expectedLastSequence but it is = ${step.sequence}";
       };
    };
    
    log.info "";
    log.info 'Test Step "' + testRunner.runContext.currentStep.name + '" done...';

    Regards,

    Todd