All about HTTP responses with WebMocks in Delphi
Tags: delphi, testing, tdd, webmocks
Published: 2021-02-15 11:28:18

In the previous post [Testing HTTP clients in Delphi with DUnitX and WebMocks](https://dev.to/rhatherall/testing-http-clients-in-delphi-with-dunitx-and-webmocks-25ck) we looked at a DUnitX test's basic structure using [WebMocks](https://github.com/appercept/Delphi-WebMocks) to stub an HTTP endpoint. At this point, it appears very simplistic and not at all like many real-world HTTP interactions. Most requests don't merely respond "OK" with no content. Let's explore how and what content we can mock, giving your test subjects scenarios allowing you to write tests asserting their behaviour.

# The Defaults
When stubbing a request without specifying the response, the default is empty but successful:
```
HTTP/1.1 200 OK
content-type: text/plain; charset=utf-8
content-length: 0
```

This response differs from not stubbing the request only in status code which would be `501 Not Implemented`. So, how do we customize the response? Using `ToRespond` is the answer. Let's take a look at what we can do by chaining a `ToRespond` call.

# Setting Status Codes
The `ToRespond` function accepts an optional argument `AResponseStatus` allowing you to specify the response status code. Returning a status of `204 No Content` is achieved with:
```Pascal
WebMock.StubRequest('GET', '/').ToRespond(204);
```

Not all of us have a comprehensive knowledge of HTTP status codes, so, thankfully `ToRespond` will accept an enum value instead, allowing you to have descriptive symbols in your test code without the need to add comments. Add `WebMock.ResponseStatus` to your `uses` clause, and you will be able to refer to status `204` as `NoContent`:
```Pascal
WebMock.StubRequest('GET', '/').ToRespond(NoContent);
```

I'll pause a moment here to point out some small syntactic sugar WebMocks provides: `WithStatus`. By chaining `WithStatus` after `ToRespond` the test becomes more descriptive:
```Pascal
WebMock.StubRequest('GET', '/')
  .ToRespond
  .WithStatus(204);

// or

WebMock.StubRequest('GET', '/')
  .ToRespond
  .WithStatus(NoContent);
```

Using `WithStatus` also provides the ability to return a custom status code and text:
```Pascal
WebMock.StubRequest('GET', '/')
  .ToRespond
  .WithStatus(321, 'Back In The Room');
```

Now we know how to change the response status. Unless you are returning `204 No Content` however, you'll likely want to send some data back too. Let's take a look at setting the body content next.

# Setting Body Content
As we saw earlier, the default response content is a zero-length plain-text response with the UTF-8 character set. Setting body content is done using `WithBody`:
```Pascal
WebMock.StubRequest('GET', '/')
  .ToRespond
  .WithBody('Hello');
```

That's all well and good for plain-text, but you're quite likely to want to return something else like JSON. That's easy enough, specify a second argument with a content-type:
```Pascal
WebMock.StubRequest('GET', '/')
  .ToRespond
  .WithBody('{ "key": "value" }', 'application/json');
```

Now we know how to respond with small snippets of data, what if we need something larger — or not easily represented in text? That's where `WithBodyFile` comes in. You provide a path to a file, and WebMocks will attempt to return it with the correct content type.
```Pascal
WebMock.StubRequest('GET', '/video')
  .ToRespond
  .WithBodyFile('video.mp4');
```

Again, as with `WithBody`, `WithBodyFile` accepts a second argument for content-type if the file type is not commonly recognized or ambiguous.
```Pascal
WebMock.StubRequest('GET', '/video')
  .ToRespond
  .WithBodyFile('video.3gp', 'video/3gpp');
```

# Adding Headers
When testing APIs, you will, at some point, need to respond with specific headers. For example in ReST API designs, it is common to return a `location` header when creating a resource and responding `201 Created`:
```Pascal
WebMock.StubRequest('POST', '/resources')
  .ToRespond
  .WithStatus(Created)
  .WithHeader('location', 'http://example.com/resources/1');
```

You can chain as many calls to `WithHeader` as you like to build up a list of headers.
```Pascal
WebMock.StubRequest('GET', '/resources/1')
  .ToRespond
  .WithHeader('cache-control', 'no-cache')
  .WithHeader('last-modified', 'Sat, 13 Feb 2021 12:45:26 GMT');
```

As a convenience, seeing as it is common in Delphi to handle HTTP headers in a `TStringList`, WebMocks provides `WithHeaders` accepting a `TStrings` instance. This allows you to populate a response with headers from an existing list of header values:
```Pascal
var
  Headers: TStringList;
begin
  Headers := TStringList.Create;
  Headers.Values['cache-control'] := 'no-cache';
  Headers.Values['last-modified'] := 'Sat, 13 Feb 2021 12:45:26 GMT';

  WebMock.StubRequest('GET', '/resources/1')
    .ToRespond
    .WithHeaders(Headers);
end;
```

These previous two examples are identical in behaviour. While the call to `WithHeaders` is a convenient short-hand if you already have a collection of headers built, I believe chaining calls to `WithHeader` to be more descriptive when writing tests. Ultimately its a preference, you choose what works for you.

# What we've learnt so far
In the previous article, we saw how easy it is to set up a DUnitX project with WebMocks. In this article, we learnt how to customize HTTP responses with WebMocks using its HTTP-oriented interface methods. Give it a try in your projects and let me know how you get on in the comments or via [Twitter](https://twitter.com/RichHatherall). You can find the [demo code on GitHub](https://github.com/appercept/Delphi-WebMocks-Demos). The next part of this series will be along shortly "Matching HTTP requests with WebMocks in Delphi".