How to Mock HttpRequestData for Unit Testing in Azure Functions

It turns out that unit testing Azure Function Http Triggers is not straightforward. In particular, isolated functions that use the Built-in HTTP model. The built-in model passes HttpRequestData to the Run
method and returns a HttpResponseData object.
As an example, consider a function that reads the body and returns a response like so:
[Function("WeatherFunction")]
public async Task<HttpResponseData> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post")]
HttpRequestData request)
{
_logger.LogInformation("Checking the weather...");
var requestBody = await new StreamReader(request.Body).ReadToEndAsync();
// ...
var response = request.CreateResponse(HttpStatusCode.OK);
await response.WriteAsJsonAsync("no weather data found");
return response;
}
Microsoft provide a complete helper method for mocking HttpRequestData
using Moq
in the Unit testing trigger functions section of Unit Testing Durable Functions article. I reworked their sample code to fit for my scenario:
private HttpRequestData MockHttpRequestData(object requestBody, string httpMethod = "GET", HttpHeadersCollection? headers = null)
{
//
// ObjectSerializer
//
var mockObjectSerializer = new Mock<ObjectSerializer>();
mockObjectSerializer
.Setup(s => s.SerializeAsync(It.IsAny<Stream>(), It.IsAny<object?>(), It.IsAny<Type>(), It.IsAny<CancellationToken>()))
.Returns<Stream, object?, Type, CancellationToken>(async (stream, value, type, token) => { await JsonSerializer.SerializeAsync(stream, value, type, cancellationToken: token); });
var workerOptions = new WorkerOptions { Serializer = mockObjectSerializer.Object };
var mockOptions = new Mock<IOptions<WorkerOptions>>();
mockOptions.Setup(o => o.Value).Returns(workerOptions);
//
// IServiceProvider
//
var mockServiceProvider = new Mock<IServiceProvider>();
mockServiceProvider.Setup(sp => sp.GetService(typeof(IOptions<WorkerOptions>)))
.Returns(mockOptions.Object);
mockServiceProvider.Setup(sp => sp.GetService(typeof(ObjectSerializer)))
.Returns(mockObjectSerializer.Object);
//
// FunctionContext
//
var mockFunctionContext = new Mock<FunctionContext>();
mockFunctionContext.SetupGet(c => c.InstanceServices).Returns(mockServiceProvider.Object);
//
// HttpRequestData
//
var mockHttpRequestData = new Mock<HttpRequestData>(mockFunctionContext.Object);
mockHttpRequestData.SetupGet(x => x.Method).Returns(httpMethod);
mockHttpRequestData.SetupGet(r => r.Url).Returns(new Uri("https://localhost:7075/orchestrators/HelloCities"));
//
// Headers
//
headers ??= new HttpHeadersCollection();
mockHttpRequestData.SetupGet(r => r.Headers).Returns(headers);
//
// Body
//
Stream bodyStream;
if (requestBody != null)
{
var bodyJson = System.Text.Json.JsonSerializer.Serialize(requestBody);
var bodyBytes = System.Text.Encoding.UTF8.GetBytes(bodyJson);
bodyStream = new MemoryStream(bodyBytes);
mockHttpRequestData.SetupGet(r => r.Body).Returns(bodyStream);
}
//
// HttpResponseData
//
var mockHttpResponseData = new Mock<HttpResponseData>(mockFunctionContext.Object) { DefaultValue = DefaultValue.Mock };
mockHttpResponseData.SetupProperty(r => r.StatusCode, HttpStatusCode.OK);
mockHttpResponseData.SetupProperty(r => r.Body, new MemoryStream());
mockHttpRequestData.Setup(r => r.CreateResponse())
.Returns(mockHttpResponseData.Object);
return mockHttpRequestData.Object;
}
This makes it possible to write nice clean tests and be able to mock the body, method and headers of the request and also assert on the response:
[Test]
public async Task Run_WhenProvidedWithAValidLocationAndDate_ReturnsWeatherData()
{
var body = new WeatherRequest { Date = new DateOnly(2025, 6, 15), Locations = [1] };
var request = MockHttpRequestData(body);
var function = new WeatherFunction(NullLogger<WeatherFunction>.Instance);
var response = await function.Run(request);
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
}
I have an example on github with a couple of unit tests showing how this works. POST
the following JSON to the function to step through:
{
"Date" : "2025-06-15",
"Locations" : [1]
}
Useful Resources
The documentation is pretty comprehensive, its just a little difficult to find:
Subscribe to my newsletter
Read articles from John directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
