Testing HTTP clients in Delphi with DUnitX and WebMocks
Tags: delphi, testing, tdd, webmocks
Published: 2021-02-09 09:54:24

[Delphi](https://www.embarcadero.com/products/delphi) makes writing HTTP client code easy. In Delphi, there are many choices to build on when writing an HTTP client, including two bundled options: [Indy](https://www.indyproject.org), and [System.Net](http://docwiki.embarcadero.com/RADStudio/Sydney/en/Using_an_HTTP_Client). It doesn't matter which way you go, the problems presented when testing it is the same — HTTP clients need a server with which to interact. If you don't control the server, you can't control the outcome. If you can't control the outcome, how do you know the results your test should produce?

You might solve some of these issues by testing against a sandbox or testing environment. If you don't have these already, it can be a lot of work to set this up, and maybe it's not you providing the service? You might be depending on another team for building your backend. It might not be ready yet, and all you have is their documentation?

Another solution is to run an in-process HTTP server within your test project. You get fine-grained control over the HTTP server, but the setup code can be a lot of effort hampering progress. Also, unless you carefully craft your test code, an HTTP server's setup code may obscure your tests intentions.

With these issues in mind, I set about solving them by writing WebMocks for Delphi, freely available and open-source on [GitHub](https://github.com/appercept/Delphi-WebMocks-Demos) and available through [GetIt](https://getitnow.embarcadero.com/WebMocks-3.0/). I designed WebMocks to integrate with DUnitX, the popular unit testing framework, also useful for running integration tests. WebMocks provides an in-process HTTP server with responses defined by an HTTP domain-specific-language interface.

WebMocks allows you to focus on what's essential to your tests.

# Getting Started
You should make sure you have both DUnitX and WebMocks installed.
If you installed RAD Studio/Delphi via the web installer, installing DUnitX is as simple as checking the box *DUnit Unit Testing Frameworks* under *Additional Options* in the *Platforms and Extensions Manager*.
![1. RAD Studio - Additional Options](https://dev-to-uploads.s3.amazonaws.com/i/ibnp4w794925f5vspsh3.png)

The quickest and easiest way to install WebMocks is via the GetIt Package Manager. Search for *WebMocks* and click *Install*.
![2. GetIt Package Manager](https://dev-to-uploads.s3.amazonaws.com/i/s9pebrk4sd817yss3s15.png)

Let's take a look at the most basic usage of WebMocks within a DUnitX test. We will use the `THTTPClient` as the "class under test" so we don't need to write any additional classes. Testing an existing class like this will allow us to focus on the behaviour of WebMocks.

Now, we can start setting up our project. Create a new DUnitX Project found under *File > New > Other.. > DUnitX*.

Make sure *Create Test Unit* and *Create Setup and TearDown Methods* are selected. Give the TestFixture Class a name, such as *TBasicDemoTests* and click "OK". Save your project and unit before continuing (Shift+Ctrl+S).
![3. New DUnitX Project](https://dev-to-uploads.s3.amazonaws.com/i/1stph9jx2rsuz4nprd32.png)

Next, we need to configure WebMocks in our TestFixture class: Add a private member `WebMock: TWebMock` to the TestFixture class.

Declare a member for the "class under test" too — `Client: THTTPClient` in our example.

Add the missing dependencies by adding `System.Net.HttpClient` and `WebMock` to your `uses` block. You should initialise and clean up these dependencies in your `Setup` and `TearDown` procedures.

You should now have a unit that looks like:
![4. Ready](https://dev-to-uploads.s3.amazonaws.com/i/cmigrv8qwz1lmc7isx4k.png)
 
Now you're ready to write some tests.

# Writing your first test with WebMocks
Let's add the most basic example of a WebMock stubbed request.

Start by adding a new test procedure in the public section and complete your class by pressing Shift+Ctrl+C.
```Pascal
[Test]
procedure Get_WhenStubbed_ReturnsOK;
```
We might write our test like this:
1. We need a local variable to keep track of our HTTP interactions — `LResponse: IHTTPResponse`.
2. Then we stub a "GET" request for the root path ("/").
3. Then we call the client to perform a GET request and store the response.
4. Finally, we check to see if the client received an "OK" response, represented by the HTTP status code `200`.
```Pascal
procedure TBasicDemoTests.Get_WhenStubbed_ReturnsOK;
var
  LResponse: IHTTPResponse;
begin
  WebMock.StubRequest('GET', '/');

  LResponse := Client.Get(WebMock.URLFor('/'));

  Assert.AreEqual(200, LResponse.StatusCode);
end;
```
Let's run it without debugging (Shift+Ctrl+F9) and see what happens.

Now, if everything worked correctly, you should finally be able to see your test results:
![6. Results](https://dev-to-uploads.s3.amazonaws.com/i/fkncxs78edjj51yik4ex.png)

# Give WebMocks a try!
WebMocks makes the tricky task of writing tests for HTTP clients simple. In the next in this series we learn all about HTTP responses with WebMocks in Delphi. You can find the [code for this demo on GitHub](https://github.com/appercept/Delphi-WebMocks-Demos). You can reach out to me on Twitter [@RichHatherall](https://twitter.com/RichHatherall).