# Kiota Client Unit Testing: mocking data

**Date:** 2025-04-01  
**Author:** Kees C. Bakker  
**Categories:** .NET / C#  
**Original:** https://keestalkstech.com/kiota-client-unit-testing-mocking-data/

![Kiota Client Unit Testing: mocking data](https://keestalkstech.com/wp-content/uploads/2025/04/hans-reniers-lQGJCMY5qcM-unsplash.jpg)

---

After implementing [Kiota clients with resilience](https://keestalkstech.com/kiota-dependency-injection-and-resilience/), I felt the need to spend some time on unit testing them. The [Kiota docs on unit testing uses NSubstitute](https://learn.microsoft.com/en-us/openapi/kiota/testing) to override the response of the adapter. After some testing (pun intended), I did not feel satisfied with the results; we should be able to use the "normal" way of testing an `HttpClient`, right?

[Nick Chapsas](https://www.youtube.com/@nickchapsas) makes an excellent point in his video titled ["You are mocking the HttpClient the wrong way"](https://www.youtube.com/watch?v=7OFZZAHGv9o). He proposes to use the [RichardSzalay.MockHttp](https://github.com/richardszalay/mockhttp) package for some excellent mocking. In this blog, I'll show how to use the package together with Kiota.

## Test using JSON strings

The *easiest* way to make the Kiota client testable, is to inject the string value of the JSON into the HTTP client using the [RichardSzalay.MockHttp](https://github.com/richardszalay/mockhttp) package:

```
[Fact]
public async Task KiotaPetStoreClientWithString()
{
    // arrange
    var json = @"
    [
      {
        ""id"": 42,
        ""category"": { ""id"": 1, ""name"": ""dog"" },
        ""name"": ""Bandit Heeler"",
        ""photoUrls"": [""https://upload.wikimedia.org/wikipedia/en/9/90/Bandit_Heeler.png""],
        ""tags"": [ { ""id"": 1, ""name"": ""cartoon"" } ],
        ""status"": ""available""
      },
      {
        ""id"": 1337,
        ""category"": { ""id"": 1, ""name"": ""dog"" },
        ""name"": ""Scooby-Doo"",
        ""photoUrls"": [""https://upload.wikimedia.org/wikipedia/en/5/53/Scooby-Doo.png""],
        ""tags"": [ { ""id"": 1, ""name"": ""cartoon"" } ],
        ""status"": ""available""
      }
    ]";

    var mockHttp = new MockHttpMessageHandler();
    mockHttp
        .When(HttpMethod.Get, "/v2/pet/findByStatus?status=available")
        .Respond(HttpStatusCode.OK, "application/json", json);

    var client = new PetStoreClient(
        new DefaultRequestAdapter(
            new AnonymousAuthenticationProvider(),
            httpClient: mockHttp.ToHttpClient()
        )
    );

    // act
    var result = await client.Pet.FindByStatus.GetAsync(x =>
    {
        x.QueryParameters.Status = [GetStatusQueryParameterType.Available];
    });

    // assert
    result.Should().NotBeNull();
    result.Count.Should().Be(2);

    result[0].Id.Should().Be(42);
    result[0].Name.Should().Be("Bandit Heeler");

    result[1].Id.Should().Be(1337);
    result[1].Name.Should().Be("Scooby-Doo");
}
```

## Test using objects

We can do one better... by using objects. There is just one caveat; you need to do the serialization yourself (so basically you're still doing strings).

```
[Fact]
public async Task KiotaPetStoreClientWithMockedObjects()
{
    // arrange
    var tag = new Tag { Id = 1, Name = "cartoon" };
    var category = new Category { Id = 1, Name = "Dogs" };
    var pets = new Pet[] {
        new Pet
        {
            Id = 42,
            Name = "Bandit Heeler",
            Category = category,
            PhotoUrls = [ "https://upload.wikimedia.org/wikipedia/en/9/90/Bandit_Heeler.png" ],
            Tags = [ tag ],
            Status = Pet_status.Available
        },
        new Pet
        {
            Id = 1337,
            Name = "Scooby-Doo",
            Category = category,
            PhotoUrls = [ "https://upload.wikimedia.org/wikipedia/en/5/53/Scooby-Doo.png" ],
            Tags = [ tag ],
            Status = Pet_status.Available
        }
    };

    var serializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);
    serializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));

    var jsonData = JsonSerializer.Serialize(pets, serializerOptions);

    var mockHttp = new MockHttpMessageHandler();
    mockHttp
        .When(HttpMethod.Get, "/v2/pet/findByStatus?status=available")
        .Respond(HttpStatusCode.OK, "application/json", jsonData);

    var client = new PetStoreClient(
        new DefaultRequestAdapter(
            new AnonymousAuthenticationProvider(),
            httpClient: mockHttp.ToHttpClient()
        )
    );

    // act
    var result = await client.Pet.FindByStatus.GetAsync(x =>
    {
        x.QueryParameters.Status = [GetStatusQueryParameterType.Available];
    });

    // assert
    result.Should().NotBeNull();
    result.Count.Should().Be(2);

    result[0].Id.Should().Be(42);
    result[0].Name.Should().Be("Bandit Heeler");

    result[1].Id.Should().Be(1337);
    result[1].Name.Should().Be("Scooby-Doo");
}
```

## Bundling it together

I like the fact that we reuse the data objects that are created by the Kiota generator. Now, we could create a `MockedPetStoreClientFactory` that can act as a factory and a wrapper, making the calls testable. Observe the following:

```
﻿using Ktt.Resilience.Clients.Kiota.HttpClients.PetStore;
using Ktt.Resilience.Clients.Kiota.HttpClients.PetStore.Models;
using Microsoft.Kiota.Abstractions.Authentication;
using Microsoft.Kiota.Bundle;
using RichardSzalay.MockHttp;
using System.Net;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Ktt.Resilience.Tests.Mocks;

public class MockedPetStoreClientFactory
{
    private readonly JsonSerializerOptions _serializerOptions;

    public List Pets { get; set; } = [];

    public MockedPetStoreClientFactory()
    {
        _serializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);
        _serializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
    }

    public PetStoreClient CreateClient()
    {
        string SerializePets(Pet_status status)
        {
            var pets = Pets.Where(x => x.Status == status);
            return JsonSerializer.Serialize(pets, _serializerOptions);
        }

        var mockHttp = new MockHttpMessageHandler();

        mockHttp
            .When(HttpMethod.Get, "/v2/pet/findByStatus?status=available")
            .Respond(HttpStatusCode.OK, "application/json", SerializePets(Pet_status.Available));

        mockHttp
            .When(HttpMethod.Get, "/v2/pet/findByStatus?status=pending")
            .Respond(HttpStatusCode.OK, "application/json", SerializePets(Pet_status.Pending));

        mockHttp
            .When(HttpMethod.Get, "/v2/pet/findByStatus?status=sold")
            .Respond(HttpStatusCode.OK, "application/json", SerializePets(Pet_status.Sold));

        var client = new PetStoreClient(
            new DefaultRequestAdapter(
                new AnonymousAuthenticationProvider(),
                httpClient: mockHttp.ToHttpClient()
            )
        );

        return client;

    }
}
```

Now that we have a factory, it becomes easier to focus on the actual testing:

```
[Fact]
public async Task KiotaPetStoreMockedClient()
{
    // arrange
    var tag = new Tag { Id = 1, Name = "cartoon" };
    var category = new Category { Id = 1, Name = "Dogs" };
    var pets = new Pet[] {
        new Pet
        {
            Id = 42,
            Name = "Bandit Heeler",
            Category = category,
            PhotoUrls = [ "https://upload.wikimedia.org/wikipedia/en/9/90/Bandit_Heeler.png" ],
            Tags = [ tag ],
            Status = Pet_status.Available
        },
        new Pet
        {
            Id = 1337,
            Name = "Scooby-Doo",
            Category = category,
            PhotoUrls = [ "https://upload.wikimedia.org/wikipedia/en/5/53/Scooby-Doo.png" ],
            Tags = [ tag ],
            Status = Pet_status.Pending
        },
        new Pet
        {
            Id = 1950,
            Name = "Snoopy",
            Category = category,
            PhotoUrls = [ "https://upload.wikimedia.org/wikipedia/en/5/53/Snoopy_Peanuts.png" ],
            Tags = [ tag ],
            Status = Pet_status.Sold
        }
    };

    var mock = new MockedPetStoreClientFactory
    {
        Pets = [.. pets]
    };

    var client = mock.CreateClient();

    // act
    var availablePets = await client.Pet.FindByStatus.GetAsync(x =>
    {
        x.QueryParameters.Status = [GetStatusQueryParameterType.Available];
    });
    var pendingPets = await client.Pet.FindByStatus.GetAsync(x =>
    {
        x.QueryParameters.Status = [GetStatusQueryParameterType.Pending];
    });
    var soldPets = await client.Pet.FindByStatus.GetAsync(x =>
    {
        x.QueryParameters.Status = [GetStatusQueryParameterType.Sold];
    });

    // assert
    availablePets.Should().HaveCount(1);
    availablePets[0].Id.Should().Be(42);

    pendingPets.Should().HaveCount(1);
    pendingPets[0].Id.Should().Be(1337);

    soldPets.Should().HaveCount(1);
    soldPets[0].Id.Should().Be(1950);
}
```

### How about dependency injection?

This `MockedPetStoreClientFactory` makes it also really easy to override dependency injection. You can register the client as a factory in the service collection.

```
[Fact]
public async Task KiotaPetStoreDependencyInjection()
{
    // arrange
    var factory = new MockedPetStoreClientFactory
    {
        Pets = {
            new Pet
            {
                Id = 42,
                Name = "Bandit Heeler",
                Category = new Category { Id = 1, Name = "Dogs" },
                PhotoUrls = [ "https://upload.wikimedia.org/wikipedia/en/9/90/Bandit_Heeler.png" ],
                Tags = [ new Tag { Id = 1, Name = "cartoon" } ],
                Status = Pet_status.Available
            }
        }
    };

    var services = new ServiceCollection();
    services.AddSingleton(x => factory.CreateClient());

    using var provider = services.BuildServiceProvider();
    var client = provider.GetRequiredService();

    // act
    var availablePets = await client.Pet.FindByStatus.GetAsync(x =>
    {
        x.QueryParameters.Status = [GetStatusQueryParameterType.Available];
    });

    // assert
    availablePets.Should().HaveCount(1);
    availablePets[0].Id.Should().Be(42);
}
```

This makes API testing way easier.

## Final thoughts

There are a lot of options. As long as you stick to the usage of the `HttpClient`, the word is your oyster. For more information on Kiota and resilience, check [](https://keestalkstech.com/kiota-dependency-injection-and-resilience/)[Kiota, dependency injection and resilience](https://keestalkstech.com/kiota-dependency-injection-and-resilience/) or [](https://keestalkstech.com/implementing-http-resilience-by-microsoft/)[Implementing HTTP Resilience by Microsoft](https://keestalkstech.com/implementing-http-resilience-by-microsoft/).

The code is on GitHub, so check it out: [code gallery / 12. HTTP and resilience](https://github.com/KeesCBakker/keestalkstech-code-gallery/tree/main/12.http-and-resilience).
