Unit Testing HttpRequest in C#

For most of the recent projects I have been involved, there was always a dependency consumed via an HTTP call. These were downstream services, other microservices or 3rd party systems. Depending on the architecture and code flow, I have seen a huge need for mocking HttpRequest starting from unit tests to all the way to integration tests. After trying different options so far, I ended up using the following flow and happy to share for those of you dealing with similar things.

HttpRequest Body

Most probably this is something action as the main input to your business logic somewhere either at Controller or maybe somewhere at service layer. Regardless of the case, I found the following method of mocking the most effective and flexible.

public class HttpRequestTests
{
    private MemoryStream _memoryStream;
    private Mock<HttpRequest> _mockRequest;

    [TestInitialize]
    public void Init()
    {
        _mockRequest = CreateMockRequest(new TestBodyData());
    }

    [TestCleanup]
    public void Cleanup()
    {
        _memoryStream.Dispose();
    }

    private Mock<HttpRequest> CreateMockRequest(object body)
    {
        var json = JsonConvert.SerializeObject(body);
        var byteArray = Encoding.ASCII.GetBytes(json);

        _memoryStream = new MemoryStream(byteArray);
        _memoryStream.Flush();
        _memoryStream.Position = 0;

        var mockRequest = new Mock<HttpRequest>();
        mockRequest.Setup(x => x.Body).Returns(_memoryStream);

        return mockRequest;
    }
}

As seen from the code, we are converting a simple DTO into a JSON string and writing it to MemoryStream at test initialization. During the test cleanup, we are releasing it from the memory so other tests can run in isolation. This gives an opportunity to fill in the body with any type of data you need.

Typically MemoryStream is used as part of using(var ms = MemoryStream(byteArray) but doing this way disposes the stream after program flow exits Init function and gives us runtime exception. This is why MemoryStream is only disposed at the cleanup. This was a tiny detail but led me spend a couple good minutes to realise…

HttpRequest Query Parameters

This has taken for me to get to the bottom of it after reading some posts and how Microsoft teams implemented at large, i.e. Github. Micorosft Docs came to the rescue and I ended up mocking the query parameters of the request like below.

private MockQueryParameters(string param1, string param2)
{
    var paramsDictionary = new Dictionary<string, StringValues>
    {
        { "param1", param1 },
        { "param2", param2 }
    };

    _mockRequest.Setup(i => i.Query).Returns(new QueryCollection(paramsDictionary));
}

This code assumes that you access to query string params using a pattern like var param1= request.Query["param1"];.

I hope you find these bits useful for your tests going forward. I also see in the future if there are breaking changes, I’ll try to update these samples. However, I believe these classes are so much crucial to Http layer in the ecosystem so it is less likely to have a dramatic change in the usage.

Full code

public class HttpRequestTests
{
    private MemoryStream _memoryStream;
    private Mock<HttpRequest> _mockRequest;

    [TestInitialize]
    public void Init()
    {
        _mockRequest = CreateMockRequest(new TestBodyData());
        MockQueryParameters("test1", "test2");
    }

    [TestCleanup]
    public void Cleanup()
    {
        _memoryStream.Dispose();
    }

    private Mock<HttpRequest> CreateMockRequest(object body)
    {
        var json = JsonConvert.SerializeObject(body);
        var byteArray = Encoding.ASCII.GetBytes(json);

        _memoryStream = new MemoryStream(byteArray);
        _memoryStream.Flush();
        _memoryStream.Position = 0;

        var mockRequest = new Mock<HttpRequest>();
        mockRequest.Setup(x => x.Body).Returns(_memoryStream);

        return mockRequest;
    }

    private MockQueryParameters(string param1, string param2)
    {
        var paramsDictionary = new Dictionary<string, StringValues>
        {
            { "param1", param1 },
            { "param2", param2 }
        };

        _mockRequest.Setup(i => i.Query).Returns(new QueryCollection(paramsDictionary));
    }
}
Advertisement

Published by

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.