c# - 从扩展 HttpClient 的类中使用 GetAsync 时如何模拟它?
问题描述
我已经阅读了一些关于模拟 HttpClient 的内容,并且发现了几个问题,例如this one或this one,它们都指出,当我们想要模拟 GetAsync 等 HttpClient 方法时,我们必须改为模拟所有 HttpClient 方法调用的 SendAsync,像这样:
Mock<HttpMessageHandler> _clientMock = new Mock<HttpMessageHandler>(MockBehavior.Strict);
_clientMock.Protected().Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.Returns(Task.FromResult(someResponse)).Verifiable();
var x = httpClient.GetAsync("someURL");
_clientMock.Protected().Verify(
"SendAsync",
Times.Exactly(1),
ItExpr.Is<HttpRequestMessage>(req => req.Method == HttpMethod.Get && req.RequestUri == new Uri("someURL")),
ItExpr.IsAny<CancellationToken>()
);
这很好用,如果我完全像这样运行测试,它显然通过了。
但是,我正在测试的方法如下所示:
public async Task<Response<IEnumerable<Instance>>> GetInstancesAsync(string accessToken, bool? enable = null)
{
try
{
using (var client = new Client(this._baseUrl, accessToken))
{
var url = string.Format("configurations/instances?enable={0}", enable);
// Creates a request and returns the result
HttpResponseMessage response = await client.GetAsync(url).ConfigureAwait(false);
return await response.Content.ReadAsAsync<Response<IEnumerable<Instance>>>().ConfigureAwait(false);
}
}
catch { }
return null;
}
如您所见,它使用了一个 Client,这是我们创建的一个类,它扩展了 HttpClient,我认为问题可能出在此处。当我尝试测试此方法时,上面提到的解决方案不起作用,并且永远不会调用 SendAsync。我不明白为什么。
我的单元测试目前看起来像这样:
_messageHandlerMock.Protected().Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.Returns(Task.FromResult(responseMessage)).Verifiable();
var result = await _configurationsProxy.GetInstancesAsync(ACCESS_TOKEN, true);
Assert.IsNotNull(result);
_messageHandlerMock.Protected().Verify(
"SendAsync",
Times.Exactly(1),
ItExpr.Is<HttpRequestMessage>(req => req.Method == HttpMethod.Get && req.RequestUri == new Uri(url)),
ItExpr.IsAny<CancellationToken>()
);
线路_messageHandlerMock.Protected().Verify(...)
出现故障,导致
Moq.MockException :对模拟的预期调用恰好 1 次,但为 0 次”,并且 Assert.IsNotNull(result) 也失败,结果为空。
解决方案
那我把官方答案贴在这里。很高兴它奏效了!
您没有在任何地方的新 Client(...) 中使用 _messageHandlerMock,因此它使用自己的内部版本而不是您创建的模拟。因此,它绕过了您的模拟检查。它最终在 Client 类中更新了自己的实例。
推荐阅读
- css - CSS标签填充
- android - java.lang.NoSuchMethodError: android.content.res.Configuration.setLocale(Ljava/util/Locale;)V
- python - 带有 exec 的 Python3 导入库给出未定义的变量错误
- sql-server - 在字符条件后添加空格时我可以选择一行
- asp.net - 为 MVC 应用程序选择什么 Docker Image?
- javascript - 如何使用 RxJS 恢复 websocket 连接
- python - Tensorflow:如何在维数不变的情况下对张量进行切片?
- typescript - 打字稿防止“排序导入”影响一个特定的导入
- typescript - WebStorm TypeScript 装饰器新行
- r - 如何使 ggplot2 3.0.0 中的热图图例与我的绘图高度相同?