I'm doing a mock HttpClient so I can unit test my code. I want to check the Content that is being posted.
I've done this:
MockHttpMessageHandler = new Mock<FakeHttpMessageHandler>() { CallBase = true };
HttpClient = new HttpClient(MockHttpMessageHandler.Object, false);
and
MockHttpMessageHandler.Setup(c => c.Send(It.IsAny<HttpRequestMessage>())).Returns(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
});
and
MockHttpMessageHandler.Verify(c => c.Send(It.Is<HttpRequestMessage>(
m => m.Content.Headers.ContentType.MediaType == "text/xml" &&
m.Method == HttpMethod.Post &&
m.RequestUri.ToString() == "http://www.test.com/" &&
m.Content.ReadAsStringAsync().Result == "TestContent")));
This works fine except for the Content
line. I get an error saying that the Content is Disposed.
I'm guessing this is because it's a stream.
Is there an elegant way to be able to test the Content? It would be nice to directly get access to the content because I can test for encoding problems as well.
Edit:
The HttpClient is dependency injected into a class that does this:
public class MyHttpSenderClass
{
HttpClient _httpClient; // DI populates this
//...
public async Task<HttpResponseMessage> ComposeAndsendHttpRequestMessage(string url, string payload, string mediaType, string method)
{ var httpRequestMessage = new HttpRequestMessage(method, new Uri(url));
httpRequestMessage.Content = new StringContent(payload);
httpRequestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue(mediaType);
using (_httpClient)
{
// I want to test this httpRequestMessage is correct
var responseMessage = await _httpClient.SendAsync(httpRequestMessage);
return responseMessage;
}
}
}
The exception, for clarification:
System.ObjectDisposedException: Cannot access a disposed object. Object name: 'System.Net.Http.StringContent'.
This is on the m.Content.ReadAsStringAsync().Result
part, because the Content is disposed.
I've solved this with the help of the other answers, by reading the Content in the message handler itself and storing it, then resetting the stream.
public class FakeHttpMessageHandler : HttpMessageHandler
{
public string Content { get; set; }
public virtual HttpResponseMessage Send(HttpRequestMessage request)
{
throw new NotImplementedException("Use Moq to overrite this method");
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
MemoryStream msInput = new MemoryStream();
await request.Content.CopyToAsync(msInput);
byte[] byteInput = msInput.ToArray();
msInput.Seek(0, SeekOrigin.Begin);
Content = Encoding.UTF8.GetString(byteInput);
return Send(request);
}
}
Hopefully this will help someone else trying to read the Content when mocking a HttpClient.