Search code examples
wiremockwiremock-standalone

How does "hasExactly" keyword work in WireMock JSON Stub configuration?


I have a JSON stub configuration as below -

   {
  "mappings": [
    {
      "request": {
        "method": "GET",
        "url": "/student",
        "headers": {
          "X-Request-ID": {
            "hasExactly": [
              {
                "equalTo": "Demo1"
              },
              {
                "contains": "Demo2"
              },
              {
                "doesNotContain": "Demo3"
              }
            ]
          }
        }
      },
      "response": {
        "status": 200,
        "headers": {
          "Content-Type": "application/json"
        },
        "jsonBody": {
          "studentId": 1
        }
      }
    }
  ]
}

And in Postman, I am creating request as below and it is giving response. enter image description here

As per my understanding, X-Request-ID should have exactly three values and if a value equals to "Demo1" then condition should not be evaluated for remaining two. Same goes for other values and conditions.

First Value = Demo1 -> Satisfies "equalTo": "Demo1" (this condition should not be checked for next 2)
2nd Value = Demo2 -> Satisfies "contains": "Demo2"
3rd Value = Demo3 -> Here we have only one condition left which is "doesNotContain": "Demo3" and it is not satisfied by third value.

But it seems it check for exactly three values but if the it finds same value for two conditions it matches.


Solution

  • The position of the objects within the hasExactly array are not positional, meaning that just because an object is in the first position, it will not only check the first header.

    This is causing the match to occur (where you would expect it not to), because the following checks are occurring:

    • There are three X-Request-ID headers (✅)
    • One of the X-Request-ID headers satisfies "equalTo": "Demo1" (✅ - first header)
    • One of the X-Request-ID headers satisfies "contains": "Demo2" (✅ - second header)
    • One of the X-Request-ID headers satisfies "doesNotContain": "Demo3" (✅ - first and second headers)

    You can prove this behavior with a somewhat simpler mapping:

    {
        "request": {
            "method": "GET",
            "url": "/foo",
            "headers": {
                "X-Request-ID": {
                    "hasExactly": [
                        { "equalTo": "1"},
                        { "contains": "1"}
                    ]
                }
            }
        },
        "response": {
            "status": 200
        }
    }
    

    And sending a request with the following X-Request-ID headers: X-Request-ID: 1 and X-Request-ID: 2.

    Unfortunately, I'm not sure if there is an out-of-the-box solution to your ask. I'd recommend looking at implementing a Custom Matcher to handle this logic.