调用 PostAsync 后测试 HttpRequestMessage.Content 的值

Sha*_*tin 5 .net asp.net httpclient .net-core asp.net-core

我们已经模拟了HttpMessageHandler,所以我们可以测试一个使用HttpClient.

我们在测试中的方法之一创建了一个 new HttpClient,调用PostAsync并处理了HttpClient. 我们想像这样测试ContentHTTP 请求:

Assert.Equal("", ActualHttpRequestMessage.Content.ReadAsStringAsync());
Run Code Online (Sandbox Code Playgroud)

问题是,我们“无法访问已释放的对象,”因为HttpClient处置的Content

问题我们如何检查内容?

这是我们的起订量设置。

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)
        }));
Run Code Online (Sandbox Code Playgroud)

这就是我们在被测类中使用它的方式。

new HttpClient(HttpMessageHandler);
Run Code Online (Sandbox Code Playgroud)

dka*_*man 6

将您的模拟更改为:

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)
        }));
Run Code Online (Sandbox Code Playgroud)

然后你可以这样测试:

Assert.Equal("", ActualHttpRequestContent);
Run Code Online (Sandbox Code Playgroud)

请记住,我们只能读取Content一次,因此如果您稍后尝试读取它,它将是空的。它就像一个海森堡物体。