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
Building an S3 application in Delphi
A working Delphi app that creates a bucket, lists objects, uploads and downloads files, and generates presigned URLs — the credential chain from the last post does the rest.
Read more →
Credentials for the AWS SDK for Delphi
The AWS credential provider chain, configuring credentials for different environments, and handling the exception you'll hit the first time something's wrong.
Read more →
Calling Amazon Translate from Delphi
Install the AWS SDK for Delphi, plug in credentials, and call Amazon Translate from an FMX app in under fifty lines of code.
Read more →