---
title: "How to test HttpClient inside API Tests"
description: "I am a great fan of API tests. I do like to utilize the `WebApplicationFactory` for this. I even wrote some articles about this in the past \"[*Introduction to WebApplicationFactory*](https://steven-giesel.com/blogPost/cd62475b-2c7d-4ce2-bd97-9670f91ebac8/introduction-to-webapplicationfactory)\". But what if we need to \"mock\" `HttpClient` calls inside our tests?"
updated: 2024-09-02
tags: ["C#", ".NET", "Testing"]
canonical: "https://steven-giesel.com/blogPost/47e4a351-0f1b-4bb5-a3d5-0ce4d7c1fa61/how-to-test-httpclient-inside-api-tests"
---

# How to test HttpClient inside API Tests

I am a great fan of API tests. I do like to utilize the `WebApplicationFactory` for this. I even wrote some articles about this in the past "[*Introduction to WebApplicationFactory*](https://steven-giesel.com/blogPost/cd62475b-2c7d-4ce2-bd97-9670f91ebac8/introduction-to-webapplicationfactory)". But what if we need to "mock" `HttpClient` calls inside our tests?

## The setup

Imagine the very minimalistic setup:

```csharp
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient<GreeterService>(
    o => o.BaseAddress = new Uri("https://steven-giesel.com"));
var app = builder.Build();
app.MapGet("/", async (GreeterService service) => await service.GetSomethingAsync());

app.Run();

public partial class Program;

public sealed class GreeterService
{
    private readonly HttpClient _client;

    public GreeterService(HttpClient client) => _client = client;

    public async Task<string> GetSomethingAsync() => await _client.GetStringAsync("/api");
}
```

We are utilizing a `HttpClient` inside our `GreeterService`. Now this class isn't really mockable. How should we approach that?
Because for sure we don't want to make real HTTP requests in our tests (at least to external systems) as they make the test unstable and flaky!

## The test
So let's write a very basic test with the `WebApplicationFactory`:

```csharp
public class ApiTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly WebApplicationFactory<Program> _factory;

    public ApiTests(WebApplicationFactory<Program> factory)
    {
        _factory = factory;
    }
    
    [Fact]
    public async Task ShouldGreet()
    {
        using var client = _factory.CreateClient();

        var response = await client.GetStringAsync("/");

        Assert.NotNull(response);
    }
}
```

Now this test works just fine and will probably pass (well if my website isn't down). But we want to bring everything under our control to make that test: 
 1. Stable
 2. Able to return fake data

Meet:

## `HttpMessageHandler` / `DelegatingHandler`
[`DelegatingHandler`](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.delegatinghandler?view=net-8.0) is a "middleware" for your `HttpClient`. So everytime you call `SendAsync` that handler will be invoked. Normally you would use it to do some logging or do authentication stuff and what not. But we can also use it in testing scenarios!

The handler for our test will look like this (I will put the link to the code at the end of the blog post):
```csharp
public class FakeDataHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (request.RequestUri is { AbsoluteUri: "https://steven-giesel.com/api" })
        {
            return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent("Hello World"),
            });
        }
        
        return base.SendAsync(request, cancellationToken);
    }
}
```

Now we only have to use the Handler:
```csharp
public ApiTests(WebApplicationFactory<Program> factory)
{
    _factory = factory.WithWebHostBuilder(s =>
        s.ConfigureTestServices(sc =>
        {
            sc.AddTransient<FakeDataHandler>();
            sc.ConfigureHttpClientDefaults(d =>
                d.AddHttpMessageHandler<FakeDataHandler>());
        }));
}
```

And if we build a test like this, it will pass:

```csharp
[Fact]
public async Task ShouldGreet()
{
    using var client = _factory.CreateClient();

    var response = await client.GetStringAsync("/");

    Assert.NotNull(response);
    Assert.Equal("Hello World", response);
}
```

Hurray! We did it. A super convenient way of mocking your Http requests via the `HttpClient`. And you can easily add extensions here:
1. Instead of hardcoding the data, you could also get it directly from the DI container. Where you have a mapping between an expected `Uri` and the response as string or JSON object.
2. You could also throw an exception, if the route isn't hit. So fail fast! Also bonus points: As you don't make unnecessary requests to a service!

## Resources
* GitHub Repository with all my examples: [here](https://github.com/linkdotnet/BlogExamples)
* Code for this specific blog post: [here](https://github.com/linkdotnet/BlogExamples/tree/main/FakeHttpClient)