In WireMock, how do urlEqualTo() and urlPathEqualTo() differ when a query string is present?
answer
- two axes: whole URL or path
- the question mark is the divide
- url means everything, urlPath means path
- regex forms mirror the same split
- append ?status=in-press and one stub dies
basics
~20 sWireMock's urlEqualTo matches the whole request URL, path and query string together. WireMock's urlPathEqualTo matches the path alone and ignores everything after the question mark. Add a query parameter and the urlEqualTo stub stops matching, while urlPathEqualTo still fires.
solid answer
~40 sIn WireMock, `urlEqualTo("/bindery/v2/orders")` compares the literal request URL — the path **and** the query string — against the value you gave it, so a request for `/bindery/v2/orders?status=in-press` misses the stub entirely. WireMock's `urlPathEqualTo("/bindery/v2/orders")` compares only the path portion, so the same request matches whatever query the client happens to send. WireMock offers the same split in regex form: `urlMatching(` applies its pattern to the full URL and `urlPathMatching(` to the path alone, and both must match the whole value rather than a substring of it. The practical rule is to reach for WireMock's `urlPathEqualTo(` or `urlPathMatching(` and let a query predicate carry the query, because embedding `?status=in-press` in a literal URL also pins parameter order and encoding. Neither matcher constrains the HTTP method — in WireMock that comes from `get(`, `post(` or `any(`.
code
java · 15 linesimport static com.github.tomakehurst.wiremock.client.WireMock.*;
// Whole-URL match: dies as soon as the client appends ?status=in-press
stubFor(get(urlEqualTo("/bindery/v2/orders"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("{\"orders\":[]}")));
// Path-only match: the query string is not part of the comparison
stubFor(get(urlPathEqualTo("/bindery/v2/orders"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("{\"orders\":[{\"orderId\":\"BND-4417\"}]}")));go deeper
Be ready to say which slice of the URL each WireMock matcher looks at: urlEqualTo takes the whole URL, urlPathEqualTo takes the path. Naming the pair and stating the difference in one sentence is the whole ask here.
Explain why the split exists — a query string is part of the URL, so a literal whole-URL comparison also pins parameter order and encoding. Be able to add that WireMock's regex forms mirror the same split and must match the entire value.
Offer a default you would apply across a whole suite: a path matcher plus separate query predicates, with urlEqualTo reserved for genuinely fixed URLs. Describe what breaks when a client starts appending a correlation id nobody announced.
Own the convention rather than the call. Decide whether stub sets in your organisation may embed query strings in urlEqualTo at all, and be able to defend the looser default against the risk of a stub that matches more than anyone intended.
## What a WireMock URL matcher is actually handed Every WireMock stub is built from a *request pattern*, and the URL matcher inside that pattern is handed the request target exactly as the server received it — everything from the leading slash onwards. For `GET /bindery/v2/orders?status=in-press&limit=20` that string is `/bindery/v2/orders?status=in-press&limit=20`: path and query string together, one value. The only question a URL matcher answers is which slice of that value it compares, and WireMock gives you four combinations of two independent choices — **whole URL or path only**, and **literal or regex**. ## The four matchers, side by side | WireMock matcher | Compares | Style | |---|---|---| | `urlEqualTo(` | the whole URL, path **and** query string | literal | | `urlMatching(` | the whole URL, path **and** query string | regex | | `urlPathEqualTo(` | the path only | literal | | `urlPathMatching(` | the path only | regex | Against the bookbindery order API, with the incoming request `GET /bindery/v2/orders?status=in-press`: - WireMock's `urlEqualTo("/bindery/v2/orders")` does **not** match: the declared value carries no query string and the request does. - WireMock's `urlEqualTo("/bindery/v2/orders?status=in-press")` matches, but only for that exact query string, spelled that way, in that order. - WireMock's `urlPathEqualTo("/bindery/v2/orders")` matches, and would still match with three more parameters appended. - WireMock's `urlMatching(` with the pattern `/bindery/v2/orders\?status=.*` matches, and the `?` has to be escaped precisely because the pattern is run over the full URL. - WireMock's `urlPathMatching("/bindery/v2/orders")` matches, because its pattern is applied to the path alone and the query string is never shown to it. ## The regex forms are anchored WireMock's two regex matchers require the pattern to match the **entire** value they are given, not some substring of it. That surprises people in two different ways: - WireMock's `urlPathMatching("/bindery/v2/orders")` will not match `/bindery/v2/orders/BND-4417`. You need `/bindery/v2/orders/.*`, or `/bindery/v2/orders(/.*)?` if the bare collection path must match too. - WireMock's `urlMatching("/bindery/v2/orders")` will not match a request that carries any query string at all, for exactly the same reason: the query string is part of the value being compared and the pattern does not cover it. Reading both as if an implicit `^` and `$` surrounded whatever you wrote makes each case obvious before you run the test. ## Why the query string usually belongs in its own predicate Writing the query into WireMock's `urlEqualTo(` looks economical and quietly commits the stub to three things you probably did not intend: 1. **Parameter order.** `?status=in-press&limit=20` and `?limit=20&status=in-press` are the same request to the bookbindery API and two different strings to a literal whole-URL matcher. 2. **Encoding.** A client that percent-encodes a space as `%20` and one that sends `+` produce different URLs; a literal comparison sees two different values and matches neither against the other. 3. **Completeness.** Any extra parameter the client starts sending later — a cache-buster, a correlation id, a feature flag — breaks a stub that was correct the day it was written. Pairing WireMock's `urlPathEqualTo(` with a dedicated query predicate keeps the URL matcher about the resource and lets each query criterion be stated separately, so an unrelated new parameter is simply not consulted. ## A working default - Start with WireMock's `urlPathEqualTo(` — it is the most specific matcher that will not break on an unrelated query change. - Move to WireMock's `urlPathMatching(` when one segment genuinely varies and its contents do not matter. - Reach for WireMock's `urlPathTemplate(` when the varying segment deserves a name you can constrain later. - Keep WireMock's `urlEqualTo(` for the rare call whose full URL, query string included, is fixed by the contract. - Use WireMock's `anyUrl()` only where the URL is deliberately not a criterion at all. None of these matchers says anything about the HTTP method. In WireMock the method comes from the builder that opens the pattern — `get(`, `post(`, `any(` — so `get(urlPathEqualTo("/bindery/v2/orders"))` constrains both axes while a bare `urlPathEqualTo(` constrains one. ## The same line, drawn elsewhere MockServer splits the two concerns in its own vocabulary: `request().withPath("/bindery/v2/orders")` matches the path only, and query criteria are a separate predicate there too — so the habit transfers even though none of the method names do. The one thing worth committing to memory is the asymmetry buried in the names. In a WireMock matcher name, `url` means *the whole URL*; `urlPath` means *the path*. Literal versus regex, anchored versus not, query-sensitive versus query-blind — all of it follows from that single word.
- In WireMock, does urlMatching() anchor its regex, or will a partial match do?WireMock's `urlMatching(` and `urlPathMatching(` both require the pattern to match the entire value they are handed — the full URL and the path respectively. So `urlPathMatching("/bindery/v2/orders")` will not match `/bindery/v2/orders/BND-4417`; you need `/bindery/v2/orders/.*`. Treat every WireMock URL regex as if it carried an implicit `^` and `$`.
- How would you stub two bookbindery order listings that differ only in their query string?Give both WireMock stubs the same `urlPathEqualTo("/bindery/v2/orders")` and separate them with query predicates rather than writing the query into `urlEqualTo(`. Each stub then stays readable, tolerates parameter reordering, and survives percent-encoding differences. Writing two literal whole-URL values instead couples both stubs to one client's exact serialisation of its query string.
saying these in an interview costs you the question
- Thinking WireMock's urlEqualTo ignores the query string
- Believing a WireMock urlMatching regex matches a substring
- Writing the query into urlEqualTo and pinning parameter order
- Expecting urlPathEqualTo to match longer paths beneath it
- Assuming a WireMock URL matcher also constrains the method