Mocking HttpRequest Body Content When Testing Azure Function HTTP Trigger Functions

When creating Azure Functions that are triggered by an HTTP request, you may want to write unit tests for the function Run method. These unit tests can be executed outside of the Azure Functions runtime, just like testing regular methods.

If your HTTP-triggered function takes as the function input an HttpRequest (as opposed to an automatically JSON-deserialized class) you may need to provide request data in your test.

As an example, consider the following code snippet that defines an HTTP-triggered function.

[FunctionName("Portfolio")]
[return: Queue("deposit-requests")]
public static async Task<DepositRequest> Run(
    [HttpTrigger(AuthorizationLevel.Function, "post", Route = "portfolio/{investorId}")]HttpRequest req,
    [Table("Portfolio", InvestorType.Individual, "{investorId}")] Investor investor,
    string investorId,
    ILogger log)
{
    log.LogInformation($"C# HTTP trigger function processed a request.");

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();

    log.LogInformation($"Request body: {requestBody}");

    var deposit = JsonConvert.DeserializeObject<Deposit>(requestBody);

    // etc.
}

If the  the preceding code is executed in a test, some content needs to be provided to be used when accessing req.Body. To do this using Moq a mock HttpRequest can be created that returns a specified Stream instance for req.Body.

If you want to create a request body that contains a JSON payload, you can use the following helper method in your tests:

private static Mock<HttpRequest> CreateMockRequest(object body)
{            
    var ms = new MemoryStream();
    var sw = new StreamWriter(ms);

    var json = JsonConvert.SerializeObject(body);

    sw.Write(json);
    sw.Flush();

    ms.Position = 0;

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

    return mockRequest;
}

As an example of using this method in a test:

[Fact]
public async Task ReturnCorrectDepositInformation()
{
    var deposit = new Deposit { Amount = 42 };
    var investor = new Investor { };

    Mock<HttpRequest> mockRequest = CreateMockRequest(deposit);

    DepositRequest result = await Portfolio.Run(mockRequest.Object, investor, "42", new Mock<ILogger>().Object);

    Assert.Equal(42, result.Amount);
    Assert.Same(investor, result.Investor);
}

When the preceding test is run, the function run method will get the contents of the memory stream that contains the JSON.

To learn more about using Moq to create/configure/use mock objects check out my Mocking in .NET Core Unit Tests with Moq: Getting Started Pluralsight course. or to learn more about MemoryStream and how to work with streams in C# check out my Working with Files and Streams course.

Add comment

Loading