首页 > 解决方案 > 我可以在没有包装器的情况下模拟 httpClient.PostAsync() 调用吗?

问题描述

我正在使用 Moq 编写测试,并且能够模拟 HttpClientHandler 的 GetAsync() 调用,但是当我尝试模拟 PostAsync() 时,它返回 null。有没有一种方法可以在不围绕整个 HttpClient 创建包装器的情况下模拟该功能?

下面是我用于模拟该功能的单元测试代码。

Mock<WebProxy> mockWebProxy = new Mock<WebProxy>();
        mockWebProxy.Object.Address = new Uri(configuration.GetSection("TestProxy").Value);
        mockWebProxy.Object.UseDefaultCredentials = true;
        Mock<HttpClient> mockHttpClient = new Mock<HttpClient>();
        var mockHttpClientHandler = new Mock<HttpClientHandler>();
        mockHttpClientHandler.Object.Proxy = mockWebProxy.Object;
        mockHttpClientHandler
            .Protected()
            .Setup<Task<HttpResponseMessage>>(
                "SendAsync",
                ItExpr.IsAny<HttpRequestMessage>(),
                ItExpr.IsAny<CancellationToken>()
            )
            .ReturnsAsync(new HttpResponseMessage()
            {
                StatusCode = HttpStatusCode.OK,
                Content = new StringContent("this is a test")
            })
            .Verifiable();
        mockHttpClient = new Mock<HttpClient>(mockHttpClientHandler.Object, true);

然后这里是我调用 PostAsync():

var response = await httpClient.PostAsync(new Uri(url), stringContent);

PostAsync() 在不模拟 httpClient 时有效。但是在嘲笑的时候,上面的响应是空的。这告诉我正在使用模拟的 HttpClient,因为没有响应,但我不确定为什么它为空,而不是我模拟的适用于 GetAsync() 的 HttpResponseMessage。

标签: c#unit-testingmoqdotnet-httpclient

解决方案


你将需要一个包装器。

您的设置SendAsync在基HttpMessageInvoker类中是虚拟的,因此可以覆盖,但您正在调用PostAsync,它是公共的且不可覆盖。

很酷的事情HttpClient是,一旦你把它包起来,你就可以重复使用。咬紧牙关(如果可以的话)并把它包起来。:-)


推荐阅读