Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test the value of the HttpRequestMessage.Content after calling PostAsync

We've mocked the HttpMessageHandler, so we can test a class that uses the HttpClient.

One of our methods under test creates a new HttpClient, calls PostAsync, and disposes the HttpClient. We would like to test the Content of the HTTP request like this:

Assert.Equal("", ActualHttpRequestMessage.Content.ReadAsStringAsync());

The problem is that we "Cannot access a disposed object," because the HttpClient disposes the Content.

Question How can we inspect the content?

This is our Moq setup.

MockHttpMessageHandler = new Mock<HttpMessageHandler>();

MockHttpMessageHandler
    .Protected()
    .Setup<Task<HttpResponseMessage>>(
        "SendAsync",
        ItExpr.IsAny<HttpRequestMessage>(),
        ItExpr.IsAny<CancellationToken>())
    .Callback<HttpRequestMessage, CancellationToken>(
        (httpRequestMessage, cancellationToken) =>
        {
            ActualHttpRequestMessage = httpRequestMessage;
        })
    .Returns(
        Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new StringContent(string.Empty)
        }));

This is how we are using it in the class under test.

new HttpClient(HttpMessageHandler);
like image 510
Shaun Luttin Avatar asked Jan 19 '17 02:01

Shaun Luttin


1 Answers

Change your mock to this:

MockHttpMessageHandler
    .Protected()
    .Setup<Task<HttpResponseMessage>>(
        "SendAsync",
        ItExpr.IsAny<HttpRequestMessage>(),
        ItExpr.IsAny<CancellationToken>())
    .Callback<HttpRequestMessage, CancellationToken>(
        (httpRequestMessage, cancellationToken) =>
        {
            // +++++++++++++++++++++++++++++++++++++++++
            // Read the Content here before it's disposed
            ActualHttpRequestContent = httpRequestMessage.Content
                .ReadAsStringAsync()
                .GetAwaiter()
                .GetResult();

            ActualHttpRequestMessage = httpRequestMessage;
        })
    .Returns(
        Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new StringContent(string.Empty)
        }));

Then you can test like this:

Assert.Equal("", ActualHttpRequestContent);

Keep in mind that we can only read Content once, so if you try to read it later, it will be empty. It's like a Heisenberg object.

like image 66
dkackman Avatar answered Sep 18 '22 01:09

dkackman