OpenFeign/feign · error · VerificationAssertionError
Expected: , but was
Error message
Expected: %s, but was: %s
What it means
MockClient's sequential execution mode replays recorded request/response pairs in order. When the incoming request's key does not equal the next expected RequestKey (compared with equalsExtended, which matches url and possibly headers/body), a VerificationAssertionError is thrown showing the expected and actual request keys. It signals the test issued a request different from the next one queued in the mock.
Solutions
- Reorder or add MockClient.add(requestKey, response) calls so the next expected RequestKey matches the actual outgoing request
- Print both keys and diff method, url, query params, and headers; fix the client request or the recorded RequestKey builder arguments
- If order does not matter, use MockClient.imitate() (non-sequential) instead of sequential mode
Example fix
// before mockClient.add(RequestKey.builder(HttpMethod.GET, "/users/1").build(), okResponse); // test calls GET /users/2 -> mismatch // after mockClient.add(RequestKey.builder(HttpMethod.GET, "/users/2").build(), okResponse);
Defensive patterns
Strategy: validation
Validate before calling
// Before asserting, ensure enqueued keys match the calls your client will make:
RequestKey expected = RequestKey.builder(HttpMethod.GET, url).build();
if (!expected.equalsExtended(actualRequestKey)) {
throw new IllegalStateException("Mock sequence mismatch: " + expected + " vs " + actualRequestKey);
} Try / catch
try {
response = client.call();
} catch (VerificationAssertionError e) {
// log expected vs actual request keys from e.getMessage()
throw new AssertionError("Sequential mock request mismatch: " + e.getMessage(), e);
} Prevention
- Enqueue RequestKeys in exactly the order the client will issue requests
- Build RequestKeys from the same constants used by the client target/URL
- Prefer non-sequential imitate() when request order is irrelevant
When it happens
Trigger: Calling a Feign client built with MockClient.imitateSequential() (or executing sequentially) where the outgoing request's method/url does not match the next recorded RequestKey via equalsExtended.
Common situations: Test sends requests in a different order than they were enqueued; URL built by the target differs (extra/missing path segments or query params); headers or body included in requestKey comparison differ from what was recorded; test forgot to enqueue the request that fires first (e.g. health check).
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- More executions were expected
- times must be a non negative number
- Wanted: ' ' but never invoked! Got
- Wanted: ' ' to be invoked: ' ' times but got: ' '!
- Do not wanted: ' ' but was invoked!
AI-assisted analysis of OpenFeign/feign@e2a1e27560 (2026-09-10).
Data as JSON: /api/errors/c0151b55fb052fed.
Report an issue: GitHub.
Appendix: source
Thrown at mock/src/main/java/feign/mock/MockClient.java:97
responseBuilder = executeAny(request, requestKey);
}
responseBuilder.protocolVersion(ProtocolVersion.MOCK);
return CompletableFuture.completedFuture(responseBuilder.request(request).build());
}
private Response.Builder executeSequential(RequestKey requestKey) {
Response.Builder responseBuilder;
if (responseIterator == null) {
responseIterator = responses.iterator();
}
if (!responseIterator.hasNext()) {
throw new VerificationAssertionError("Received excessive request %s", requestKey);
}
RequestResponse expectedRequestResponse = responseIterator.next();
if (!expectedRequestResponse.requestKey.equalsExtended(requestKey)) {
throw new VerificationAssertionError(
"Expected: \n%s,\nbut was: \n%s", expectedRequestResponse.requestKey, requestKey);
}
responseBuilder = expectedRequestResponse.responseBuilder;
return responseBuilder;
}
private Response.Builder executeAny(Request request, RequestKey requestKey) {
Response.Builder responseBuilder;
if (requests.containsKey(requestKey)) {
requests.get(requestKey).add(request);
} else {
requests.put(requestKey, new ArrayList<>(Arrays.asList(request)));
}
responseBuilder = getResponseBuilder(request, requestKey);
return responseBuilder;
}View on GitHub (pinned to e2a1e27560)