.NET 7,xUnit,最小起订量
我在测试时遇到错误:
// Arrange
var mockHttpClientFactory = new Mock<IHttpClientFactory>();
var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
var expectedResponseContent = "response content";
mockHttpMessageHandler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(expectedResponseContent)
});
var httpClient = new HttpClientAdapter(mockHttpMessageHandler.Object)
{
BaseAddress = new("https://stackoverflow.com")
};
mockHttpClientFactory.Setup(_ => _.CreateClient("someClient"))
.Returns(httpClient);
var controller = new SomeController(mockHttpClientFactory.Object);
// Act
var result = await controller.GetPayloadAsync();
// Assert
Assert.Equal(expectedResponseContent, result);
错误:
System.Net.Http.HttpRequestException:将内容复制到流时出错。
System.ObjectDisposeException:无法访问关闭的流。
我正在测试的代码:
await client.GetStringAsync("https://stackoverflow.com")
在测试中,我一开始只是用
HttpClient
来嘲笑 HttpClientFactory
,但这显示了错误。然后我实现了this。
但我仍然遇到同样的错误。修改如下:
class HttpClientAdapter : HttpClient, IClient
{
public HttpClientAdapter(HttpMessageHandler httpMessageHandler): base(httpMessageHandler)
{
}
public override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken = default) => base.SendAsync(request, cancellationToken);
}
有什么想法如何在不关闭流的情况下测试这个吗?
我做了什么来解决@jdweng 在评论中解释的问题。 我需要重写 2 个 Http 调用的 SendAsync 设置。这是代码。
var handlerIndex = 0;
mockHttpMessageHandler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(() =>
{
if (handlerIndex == 0)
{
handlerIndex++; // Increment the index for the second call
return new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(expectedResponseContent1)
};
}
else
{
return new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(expectedResponseContent2)
};
}
})
.Verifiable();
在
.ReturnsAsync()
中使用委托而不是直接值就足够了。
mockHttpMessageHandler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(() =>
{
return new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(expectedResponseContent)
};
});
我认为这是因为在这种情况下,Moq 每次都会执行委托代码,因此每次都会创建新的
HttpResponseMessage()
对象。在您的情况下,HttpResponseMessage()
仅创建一次,因此内部流在后续调用中可能包含不正确的状态。