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:
- Durable Functions unit testing (C# Isolated) > Unit testing trigger functions
- Guide for running C# Azure Functions in the isolated worker model > HTTP Trigger