skip to content

In MockServer, what does `withQueryStringParameter("borough", "camden")` add to an expectation?

level: juniorimportance: should knowfreq 61%

answer

  1. request side, not response side
  2. a condition, not something sent
  3. reads the URL query string
  4. one call per parameter, they accumulate

basics

~20 s

It adds a predicate to the expectation's request side. The call matches only if the URL query string carries a borough parameter whose value matches camden. A request without that parameter is simply not matched by this expectation.

solid answer

~50 s

MockServer's `withQueryStringParameter` is a **request-side matcher**, not something the server sends. It goes on the MockServer `request()` object you hand to `MockServerClient.when(...)`, beside `withPath`, `withHeader` and `withCookie`, and it narrows which incoming calls the expectation answers. On the chimney-sweep scheduling stub, MockServer's `request().withMethod("GET").withPath("/v1/sweeps").withQueryStringParameter("borough", "camden")` answers `GET /v1/sweeps?borough=camden` and leaves `GET /v1/sweeps?borough=hackney` alone. MockServer reads the parameter from the URL query string only, so a form-encoded field of the same name in a POST body is a different thing. It also compares that value literally first and then as a regular expression, so `camden` behaves exactly as written while a value carrying a dot or a plus is looser than it looks. Call it once for each parameter you want to constrain, since the calls accumulate on the same request object rather than the second replacing the first.

code

java · 14 lines
java
import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpResponse.response;

client.when(
        request()
            .withMethod("GET")
            .withPath("/v1/sweeps")
            .withQueryStringParameter("borough", "camden")
            .withQueryStringParameter("trade", "sweep"))
    .respond(
        response()
            .withStatusCode(200)
            .withHeader("Content-Type", "application/json")
            .withBody("{\"sweeps\":[{\"sweepId\":\"SW-4471\",\"borough\":\"camden\"}]}"));

go deeper

for a junior

Be able to write it: it goes on the MockServer request object inside when(...), it names a parameter and the value that parameter must have, and it decides whether an incoming call is answered.

for a middle

Explain what it does not do: MockServer reads the query string rather than the body here, and leaves every parameter it does not name completely unconstrained on the request side.

for a senior

Talk about how tightly to write it in a real suite, since a value pinned too hard breaks on harmless client changes while a value left loose lets the wrong call through unnoticed.

for a principal

Own the convention for how stub definitions are authored and reviewed across teams, so the query predicates in a shared MockServer instance stay readable and consistently scoped.

## Where the call belongs MockServer expectations are built from two objects: a `request()` describing which incoming calls the expectation applies to, and a `response()` describing what to send back. MockServer's `withQueryStringParameter` belongs to the first of those. You call it on the MockServer `request()` you hand to `MockServerClient.when(...)`, next to `withMethod`, `withPath`, `withHeader` and `withCookie`, and it narrows the set of calls the expectation answers. The word that matters is **matcher**. MockServer's `withQueryStringParameter` does not put a parameter on a request — MockServer is standing in for the chimney-sweep scheduling service, so it receives requests rather than sending them. The value you write is a condition the incoming call has to satisfy. ## What it constrains, and what it says nothing about - **It reads the URL query string.** `GET /v1/sweeps?borough=camden` satisfies MockServer's `withQueryStringParameter("borough", "camden")`; `GET /v1/sweeps` does not, because there is nothing there to satisfy the constraint. - **It compares the value, not just the name.** `GET /v1/sweeps?borough=hackney` carries the parameter but fails the value, so the MockServer expectation does not match. - **It is not a body matcher.** A form-encoded field named `borough` inside a POST body is a different thing entirely, and MockServer's query-string predicate does not see it. - **It says nothing about other parameters.** MockServer matches on a subset, so a call sending `borough=camden&trade=survey&page=3` still matches an expectation that mentions only `borough`. - **The calls accumulate.** Calling MockServer's `withQueryStringParameter` twice, once for `borough` and once for `trade`, adds two constraints to the same `request()` object rather than the second replacing the first. ## A worked expectation on the chimney-sweep scheduling stub The stub answers the scheduling list endpoint. The client under test asks for camden sweeps, and the expectation pins both the borough and the trade so a survey request cannot accidentally receive the sweep fixture. MockServer's `request().withMethod("GET").withPath("/v1/sweeps").withQueryStringParameter("borough", "camden").withQueryStringParameter("trade", "sweep")`, paired with MockServer's `response().withStatusCode(200)` and a JSON body, gives the client exactly one answer for exactly one query. Anything else the client asks — a different borough, a missing trade — falls outside this expectation, which is usually what you want while a single behaviour is under test. One caution worth carrying from the start: MockServer compares a parameter value literally first and then as a regular expression, so a value containing `.`, `+`, `?` or `|` is looser than it looks. The values `camden` and `sweep` contain no metacharacters and behave exactly as written; a media type or a signed token does not. ## The sibling predicates on the same request object | MockServer predicate | reads from | example on the sweep scheduling stub | |---|---|---| | MockServer `withQueryStringParameter` | the URL query string | `withQueryStringParameter("borough", "camden")` | | MockServer `withHeader` | the request's header fields | `withHeader("X-Sweep-Tenant", "acme\\.co")` | | MockServer `withCookie` | the request's cookies | `withCookie("sweepSession", "[0-9a-f]{32}")` | All three MockServer predicates are written the same way and behave the same way, which makes the request side easy to read once you have seen one of them. ## The same predicate in the other stub servers In WireMock the two sources are separate predicates on the request pattern, so WireMock's `withQueryParam("borough", equalTo("camden"))` covers the URL query string while WireMock's `withFormParam("trade", equalTo("sweep"))` covers a form-encoded body field, with WireMock's `havingExactly(...)` and `including(...)` available where a name repeats. Mountebank writes the same idea as data rather than as a call. A Mountebank `equals` predicate carries a `query` object holding `borough`, alongside a Mountebank `headers` object for header predicates in the same predicate block. ## First mistakes 1. **Putting it on the response.** MockServer's `withQueryStringParameter` is a request-side matcher; its response object carries the status code, headers and body that go back to the client. 2. **Expecting it to see a form field.** MockServer reads the URL query string here only, so a form-encoded booking body needs a different predicate. 3. **Assuming an unlisted parameter is forbidden.** MockServer ignores parameters the expectation never names, so the predicate is broader than the one example you had in mind. 4. **Writing a value full of punctuation and expecting a literal comparison.** MockServer falls back to a regular expression when the literal comparison fails, so escape anything you meant literally. Get those four right and the request side of a MockServer expectation stops being mysterious: it is a small list of conditions over the method, the path, the query string, the headers and the cookies, and every one of them is written in the same shape.

  • What happens to a call to `/v1/sweeps` that carries no borough parameter at all?
    It does not satisfy this expectation. MockServer needs something in the incoming call for each constraint the `request()` object names, and a missing parameter leaves the borough constraint unsatisfied, so this expectation does not answer the call. Whether anything else answers it depends on the other expectations registered on that MockServer instance.
  • How do you constrain two query parameters on the same MockServer expectation?
    Call MockServer's `withQueryStringParameter` once for each. The calls accumulate on the same MockServer `request()` object, so `withQueryStringParameter("borough", "camden").withQueryStringParameter("trade", "sweep")` requires both to be satisfied. The second call does not replace the first, and the resulting expectation still says nothing about any other parameter the client happens to send.

saying these in an interview costs you the question

  • Thinks the method makes MockServer send a query parameter to somebody
  • Puts a request matcher on the response object
  • Expects it to match a form-encoded field inside a POST body
  • Believes a second call replaces the first parameter constraint
  • Assumes the parameter name alone matches, whatever the value