Asserting HTTP requests with WebMocks in Delphi
The other half of testing HTTP code with WebMocks: verifying that the right requests were made, with the right details, the right number of times.
Contents
The previous three articles in this series covered the mocking side of testing HTTP clients with WebMocks: stubbing requests, defining the responses to return, and matching the incoming traffic that came through. That's half the job. The other half is the question every test eventually asks: did my code make the request it was supposed to?
That's where assertions come in. Where StubRequest says "when this request comes in, respond with X," Assert says "after the test runs, verify that this request was made (or wasn't)."
A basic assertion
The simplest assertion checks that a request was made:
procedure TMyTests.CreateUser_SendsPostRequest;
begin
WebMock.StubRequest('POST', '/users').ToRespond.WithStatus(201);
Client.CreateUser('alice@example.com');
WebMock.Assert.Post('/users').WasRequested;
end;
WebMocks provides shorthand methods for each common HTTP verb: Get, Post, Put, Patch, Delete, and Head. They all take a path string and read like English at the call site. The assertion fails if the test didn't make a matching request.
WasNotRequested is just as useful, particularly when business logic decides whether to make the call at all. Cache hits, change detection, feature flags, rate-limit checks: anywhere the network request is conditional, you want a test that exercises the no-request path.
procedure TMyTests.GetUser_WhenCached_DoesNotFetchFromServer;
begin
WebMock.StubRequest('GET', '/users/1').ToRespond.WithStatus(200);
Client.PrimeCache(1, existingUser);
Client.GetUser(1);
WebMock.Assert.Get('/users/1').WasNotRequested;
end;
If the cache check regresses and the client fetches anyway, the test catches it.
Asserting on request details
Often "the right method and path were used" isn't enough; you want to confirm the request also carried the expected headers, query parameters, or body. The full matcher vocabulary from the previous article on request matching is available on assertions:
WebMock.Assert
.Post('/users')
.WithHeader('content-type', 'application/json')
.WithJSON('email', 'alice@example.com')
.WasRequested;
WithHeader, WithJSON, WithFormData, WithQueryParam, WithBody, WithXML, and the bulk WithHeaders: the same set that drives StubRequest, with the regex variants and typed JSON matching (string, integer, float, boolean) all working the same way. If you can match a request to stub it, you can match it to assert it was made.
Matching variable URIs
Tests often deal with URIs that vary at runtime: a dynamic resource ID, a generated session token, a request-specific path. For those, fall back to the long-hand Request form, which accepts either a string or a regular expression for the URI:
uses
System.RegularExpressions;
WebMock.Assert
.Request('GET', TRegEx.Create('/users/\d+'))
.WasRequested;
The verb shorthands (Get, Post, etc.) only take string URIs; the long-hand Request(method, regex) is the form to reach for when the URI isn't fixed.
Where assertions sit in the test
A WebMocks test ends up with a natural rhythm:
- Arrange:
WebMock.StubRequest(...)calls that set up the responses your code under test will see. - Act: call the code under test.
- Assert: your usual DUnitX
Assert.AreEqualchecks on the application-level behaviour, followed byWebMock.Assert.Get(...)/Post(...)/ etc. checks on the HTTP traffic.
Together they cover both sides: did the code do the right thing internally, and did it talk to the network the way it should have.
What next?
That covers the basics of testing HTTP code with WebMocks in Delphi: setup, responses, request matching, and assertions. Enough for the HTTP layer of most Delphi applications.
There's more you can do once you're past the basics: testing OAuth and bearer-token flows, mocking AWS Signature V4 signed requests, simulating retry and rate-limit behaviour, using WebMocks in larger integration tests. If any of that would be useful, or you're stuck testing something specific with WebMocks and can't see how, get in touch. Enough interest and we'll do an advanced series.
WebMocks for Delphi is on GitHub, with demos for these articles in Delphi-WebMocks-Demos. Let me know what you build.
More posts
Build it with AI? Why the AWS SDK for Delphi still wins
Generating AWS code with AI works fine for a one-off script. The moment it deploys to AWS — credentials, STS, retries — the £149 SDK for Delphi is the cheaper choice.
Read more →
Announcement: AWS SDK for Delphi 2.1 — New platforms and Process Credentials
2.1 adds WinARM64EC for ARM-based Windows devices and the modern LLVM-based Win64x compiler target. Plus Process Credentials for custom credential providers.
Read more →
Announcement: AWS SDK for Delphi 2.0 — SQS moves to JSON, SES v2 expanded
Major version: SQS moves to the modern JSON protocol and SES v2 expands. Both bring breaking interface changes — read before you upgrade.
Read more →