Search code examples
javadatatablehashmapcucumberrest-assured

How to match a parameter value which contains ("${") using Cucumber DataTable in Java


I have the below Cucumber scenario with data table. I want to set query parameters in REST Assured framework. Here we have key= at and value=${atToken} which I am trying to get runtime value instead of passing hardcoded value through data table. In the below setParams method, I am trying to match the ${atToken} using param.contains("${"), but I am not able to get the desired result. Please let me know what I need to change in this for loop.

for (String param : params.keySet()) {
    if (param.contains("${")) {
        params.replace(param, RUN_TIME_DATA.get(param));
    }
}

Feature file:

  And I set query parameters
  | location     | NY         |
  | at           | ${atToken} |

Stepdefintion:

@And("set {} parameters")
public void set_query_parameters(String query, DataTable params) throws IOException {
    POC.setParams(query, params.asMap());
}

Utils file:

public void setParams (String type, Map < String, String > params) throws IOException {
    for (String param : params.keySet()) {
        if (param.contains("${")) {
            params.replace(param, RUN_TIME_DATA.get(param));
        }
    }
    switch (type.toLowerCase()) {
        case "form":
            request.formParams(params);
            break;
        case "query":
            request.queryParams(params);
            break;
        case "path":
            request.pathParams(params);
            break;

    }
}

Hooks file:

@Before
public void beforeScenario() throws Exception {
    RUN_TIME_DATA.put("atToken", POC.createAuth());
}

Solution

  • If I understood correctly your quetion, there are a few issues with your implementation.

    First of all, you have a gherkin instruction as And I set query parameters but the step definition is @And("set {} parameters")

    As you defined "query" in your step definition, I assume that you have a scenario like this.

    Scenario Outline: Params scenario
    Given ...
    When ...
    Then ...
        And I set "<queryType>" parameters
          | location | NY         |
          | at       | ${atToken} |
        Examples:
          | queryType |
          | form      |
          | path      |
    
    

    Second problem is that params.asMap() does not create a mutable map but your setParams method will need a mutable one.

    @And("I set {string} parameters")
    public void set_query_parameters(String queryType, DataTable params) throws IOException {
        // POC.setParams(queryType, params.asMap()); // not mutable map
        POC.setParams(queryType, new HashMap(params.asMap()));
    }
    

    The main issue in your loop was that you were searching $ symbol in key instead of value.

    public void setParams (String type, Map<String, String> params) throws IOException {
          for (Map.Entry<String, String> entry : params.entrySet()) {
             final String key = entry.getKey();
             final String value = entry.getValue();
    
             // if value is parameterized
             if (value.contains("${")) {
                // you are using stripped value as key in your RUN_TIME_DATA
                final String keyInRuntimeMap = getParamKeyFrom(value);                      
                params.replace(key, RUN_TIME_DATA.get(keyInRuntimeMap));
             }
          }
    
          switch (type.toLowerCase()) {
             case "form":
                request.formParams(params);
                break;
             case "query":
                request.queryParams(params);
                break;
             case "path":
                request.pathParams(params);
                break;
            // what should happen if unknown type given
             default:
                throw new IllegalArgumentException("unknown type=" + type);
          }
       }
    
         /**
        * Will strip someKey from ${someKey}
        *
        * @param text
        * @return stripped text or the original text
        */
       private String getParamKeyFrom(final String text) {
          // pattern to match -> ${someKey}
          final Pattern pattern = Pattern.compile("\\$\\{(.*)\\}");
          final Matcher matcher = pattern.matcher(text);
    
          if (matcher.find()) {
             return matcher.group(1);
          }
    
          // if pattern does not match return the same string
          return text;
       }
    

    Hope it helps.