Forum Discussion

em_qdx's avatar
em_qdx
Occasional Contributor
3 years ago
Solved

Add multiple values from a table to request headers

Is there a method for adding values from multiple records from a table (or any source) to a request name/value combination (header for instance) without knowing the "Name" and "Value" values prior to loading them?
Example:
SQL table name: RequestHeader
SQL table Fields: ID, HeaderKey, HeaderValue

In ReadyAPI: A POST request where "Name" and "Value" properties under the "Request" tab in the request must be populated from the table.
"Name" = RequestHeader.HeaderKey

"Value" = RequestHeader.HeaderValue

There could be zero or more entries in this "RequestHeader" table for multiple, discrete test cases.  The name and value of each header are unknown to the ReadyAPI request prior to being loaded to the "Name/Value" properties in the "Request" tab from the table at run time.  I want to be able to load multiple records from the table to the request header so that value from the "HeaderKey" field in each record loads to a discrete "Name" property and the value from "HeaderValue" field in each record loads to the associated "Value" property.  Can this be done in the provided ReadyAPI request object or will this require a request that is scripted in Groovy?  If this request must be scripted, are there any examples of this specific scenario?

  • ChrisAdams's avatar
    ChrisAdams
    3 years ago

    Hi,

     

    I think I have something for you.

     

    I have built a basic test that looks like this....

     

    In relation to yours, Mock Headers equals you Test Header select.  The Rest Request is your Eligibility Request.  So, one new step before and two new steps in between.

     

    The first step, Initialise Headers allows us to blow away any headers from a previous test or previous iteration of your outer loop.  It looks like this...

    // Need this to build the object for the headers...
    import com.eviware.soapui.support.types.StringToStringMap;
    
    // Get the test step of interest...
    def testStep = testRunner.testCase.getTestStepByName("REST Request");
    
    // Get the request object fo rthe test step
    def testRequest = testStep.testRequest;
    
    // Create an empty map.
    def newHeaders = new StringToStringMap();
    
    // Add the empty map to blow away previously added headers.
    testRequest.setRequestHeaders(newHeaders);

     

    As I don't have the db set-up you have, my Mock Headers data source has several rows.  Think of these as the next batch of headers to apply to the test request.

     

    Here is what my datasource looks like....

     

    The next step is Set Headers.  Here's the Groovy script.

    // Need this to build the object for the headers...
    import com.eviware.soapui.support.types.StringToStringMap;
    
    // Get the test step of interest...
    def testStep = testRunner.testCase.getTestStepByName("REST Request");
    
    // Get the request object for the test step
    def testRequest = testStep.testRequest;
    
    // Grab the header and value from the Mock Header datasource for this iteration only...
    def header = context.expand( '${Mock headers - DataSource#header}' );
    def value = context.expand( '${Mock headers - DataSource#value}' );
    
    // Get headers we've added so far.  On the first iteration this will be empty.
    def currentHeaders = testRequest.getRequestHeaders();
    
    // Add the header from the current iteration
    currentHeaders.put(header, value);
    
    // Put the request headers back into the request.
    // Note : Default headers are still there.  E.g. Connection, Accept-Encdoding, but you could use this method to override the default set if you so wish
    testRequest.setRequestHeaders(currentHeaders);
    
    // Let's have a look.  For each iteration, this log statement will get bigger.
    log.info(testRequest.getRequestHeaders());
    log.info("Mock header '${header}' set to value '${value}'.  ");
    

     

    Why do I get the headers and then add to it?  My earlier attempt just added the next.  But the effect was that it overridden previously add mock headers.  So the header applied to the test request was always the last.  So, instead, get what's there; add to it; put them back in one go.

    The next step is my datasource loop.  I've bound this to the Mock Headers data source and Set Headers Groovy.  This makes my test loop over each mock header before moving on to call the request....

     

    The datasource loop looks like....

     

    No need to look at the Rest Request yet.

     

    Run this test case as a whole and look at the Script Logs...

     

    Let's have a look at the Raw tab for the request now the test has run.

     

    Suggest you create a new test case and copy the above.  Have a play then apply to yours as it will need some tweaking for the datasource values.

12 Replies

  • richie's avatar
    richie
    Community Hero
    Hey em_qdx,

    If im understanding your scenario, the embedded functionality of ReadyAPI wont support what you want to do - you can parameterise parm values, but you cant parameterise parm names.

    So it's definitely groovy if im understanding what you want to do.

    Just curious....what sort of requests have custom headers with varying custom parameter names? I've never come across this before....custom headers, yes. But always specific clearly defined custom headers.

    Anyway, im guessing what youd need to do is use the Datasource step (data connection type) and build you request dynamically with groovy. Depending on what you need, you might need to park off the Datasource teststeps query results into a Properties teststep or myabe a DataGrid and once youve got your data saved, then dynamically build up your request sourcing the relevant data. I think i can do this in groovy (essentially cos nmrao did this for me waaaay back), but my groovy sucks and the groovy experts are better placed to help with this than i am! (@ChrisAdams / nmrao, etc.)
    Happy to try and help if theyre too busy, etc., but you really want them helping you with your groovy rather than me!

    Cheers!

    Rich
    • ChrisAdams's avatar
      ChrisAdams
      Champion Level 3

      Hi,

       

      The below Groovy script shows how to set headers for a given request.

       

      It's a real simple example that just shows how to set key-value pairs.

       

      // Need this to build the object for the headers...
      import com.eviware.soapui.support.types.StringToStringMap;
      
      // Get the test step of interest...
      def testStep = testRunner.testCase.getTestStepByName("REST Request");
      
      // Get the request object fo rthe test step
      def testRequest = testStep.testRequest;
      
      // Build our headers using StringToStringMap.  This bit could be made more custom by using a datasource, but for simplicity hard-code two values.
      def newHeaders = new StringToStringMap();
      newHeaders.put("MyCustomerHeaderOne", "MyCustomHeaderValueOne");
      newHeaders.put("MyCustomerHeaderTwo", "MyCustomHeaderValueTwo");
      newHeaders.put("MyCustomerHeaderThree", "MyCustomHeaderValueThree");
      
      // Set the request headers with our newHeaders.
      // Note : Default headers are still there.  E.g. Connection, Accept-Encdoding, but you could use this method to override the default set if you so wish
      testRequest.setRequestHeaders(newHeaders);
      

       

      Which results in the headers being assigned to the test request.  The below screenshot is from the 'Raw' tab of the request.

       

    • em_qdx's avatar
      em_qdx
      Occasional Contributor

      About the headers.  The names of the headers are defined within the APIs themselves, so they don't actually vary from request to request for the same API.  I created a database for data driven testing.  With that in mind, part of the design is to use the same ReadyAPI test for as many test cases as possible.  That means making that one ReadyAPI functional test as generic as possible.  One of the ways to do that is to use an EAV (Entity-Attribute-Value) approach to some of the tables, including the table that stores the headers for each test case.  Instead of having a table that contains a lot of columns, one for each specific header in each API, I have a header table that only has two columns instead: One column for the name of the header and the second for the value (EAV approach).  That is why I need to create a request that can load multiple headers with associated values from that table, but without knowing what the name and value of each header is prior to run time of the request.  It appears the only way to do this is to script the request itself, even if I use embedded functionality for data selects, validations, etc...Looks like I'll need to research Groovy and scripting a request test step. Thanks for the response.

      • ChrisAdams's avatar
        ChrisAdams
        Champion Level 3

        Hi,

         

        My example may be a bit simple and use hard-coded values, but it was just an example to show how to set headers.

         

        There's absolutely no reason why the example cannot be extended to use ODBC to look up the headers table and then add each applicable header for the test to the service call.