Wiremock: Verify request with duplicate query params

Created on 6 May 2016  路  20Comments  路  Source: tomakehurst/wiremock

I'm really enjoying using wiremock (2.0.10-beta) and have hit a problem trying to verify a call with duplicate query parameters:

/authz/access/12345?operations=op1&operations=op2

My naive attempt didn't work:

        wiremock.verify(getRequestedFor(urlPathEqualTo("/authz/access/12345"))
                .withQueryParam("operations", equalTo("op1"))
                .withQueryParam("operations", equalTo("op2"))
                .withHeader("Authorization", equalTo("Bearer goodtoken")));

The wiremock logs show that the second withQueryParam is overwriting the first one.

com.github.tomakehurst.wiremock.client.VerificationException: Expected at least one request matching: {
  "urlPath" : "/authz/access/12345",
  "method" : "GET",
  "headers" : {
    "Authorization" : {
      "equalTo" : "Bearer goodtoken"
    }
  },
  "queryParameters" : {
    "operations" : {
      "equalTo" : "op2"
    }
  }
}

Is this a type of verification that Wiremock would consider supporting?

In the meantime, I'm just using the following workaround (and hoping for consistent ordering):

        wiremock.verify(getRequestedFor(urlEqualTo("/authz/access/12345?operations=op1&operations=op2"))
                .withHeader("Authorization", equalTo("Bearer goodtoken")));
Feature request

Most helpful comment

We've just come up against this again and ended up back on this issue! Any progress yet? :D

All 20 comments

I'll have a think about that. I think just stating it twice is a bit confusing, because it's effectively an OR operation, when the DSL is implicitly AND for everything else. I agree generally that there should be some way to express this though.

Thanks! Just to confirm, I wanted to verify that both operations=op1 AND operations=op2 query params appear in one http call.

I think the only way you're going to be able to do that is by matching on the whole URL at the moment, which admittedly isn't great as it's hard not to make it ordering dependent.

I'm re-writing the whole matching system at the moment, so you've raised this at a good moment. I think this problem will apply to headers too, so ought to be fixed.

+1 having the same issue

馃憤 need this for headers.

Was this feature ever added?

I too need be able match the same query parameter to multiple values.

any update for this feature?

will this be ever implemented?

I am also having this problem. It is a really a useful feature. Was it implemented in a branch or something? If not, I'd love to work on this.

This is already supported with this Mock Server. It lets you define multiple parameter values as well multiple header values.

mockServerClient.when(
                request()
                .withMethod("GET")
                .withPath("/findByName")
                .withQueryStringParameters(param("name", "John", "Mike"))
        )
        .respond(
            response()
                .withBody("This is John and Mike")

        );

So the idea would be to do something like that for WireMock.

I'm working on it. Keeping the API backwards compatible is proving a bit tricky.

Here's a test case showing what I'm aiming at: https://github.com/tomakehurst/wiremock/blob/multi-value-aggregate-matching/src/test/java/com/github/tomakehurst/wiremock/MultiValuedParameterAcceptanceTest.java

matchingAll can be confusing, my initial expectation for:

.withHeader("X-My-Header", matchingAll(
    equalTo("1"),
    containing("2"),
    matching("th.*"))
)

was that one X-My-Header has to match all the patterns.

How about adding a new method:

.withRepeatingHeader("X-My-Header", matchingInAnyOrder( // or matchingExactly
    equalTo("1"),
    containing("2"),
    matching("th.*"))
)

matchingInAnyOrder will match any valid permutation of the matchers while matchingExactly will need the matchers to match in the exact order they appear.

+1

Can't wait for this feature :)

Hi @tomakehurst - did you make any progress on this?

Nope, 'fraid not.

We've just come up against this again and ended up back on this issue! Any progress yet? :D

Sorry, still not managed to get this over the line 馃槥

BTW, you can now combine custom and standard matchers so you could work around this by writing a custom matcher just for the query part.

Hi, I guess still no breakthrough ?
I tried to mix customMatcher and classic one but I'm not able to make it work with

@AutoConfigureWireMock(port = Options.DYNAMIC_PORT)

I guess extension not registered. I manage to do it by removing @AutoConfigureWireMock and use

@ClassRule
public static WireMockRule mWireMockRule = new WireMockRule(wireMockConfig()
        .port(3100)
        .extensions(new ArrayParamsMatcher()));

Both with json config as

{
    "request": {
        "method": "GET",
        "urlPath": "/comptes",
        "queryParameters": {
            "categories": {
                "equalTo": "RG"
            }
        },
        "customMatcher": {
            "name": "array-params",
            "parameters": {
                "foo": "123456789"
            }
        }
    },
    "response": {
        "status": 204
    }
}

Ideas ?

Does multiples customMatcher (may be same one) is possible on same request ?

Sorry, still not managed to get this over the line 馃槥

BTW, you can now combine custom and standard matchers so you could work around this by writing a custom matcher just for the query part.

Here's one way you can do this with hamcrest matchers to verify (contains) or ignore (containsInAnyOrder) the order of the duplicated parameters. RID_STRINGS is just a list of strings representing the expected parameter values.

        wireMockRule.stubFor(get(urlPathEqualTo("/endpoint"))
                .withQueryParam("userId", equalTo(USER_ID.toString()))
                .andMatching(request ->
                        MatchResult.of(
                                Matchers.containsInAnyOrder(RID_STRINGS.toArray(String[]::new))
                                        .matches(request.queryParameter("rids").values())
                        ))
        .willReturn(okJson(responseJson)));
Was this page helpful?
0 / 5 - 0 ratings

Related issues

joegluntz picture joegluntz  路  130Comments

jbadeau picture jbadeau  路  18Comments

AnCh7 picture AnCh7  路  15Comments

khanh-nguyen picture khanh-nguyen  路  18Comments

schoeneu picture schoeneu  路  11Comments