模拟使用 IHttpClientFactory.CreateClient 创建的 HttpClient
Mocking an HttpClient created using IHttpClientFactory.CreateClient
如标题所示,我有一些代码调用 IHttpClientFactory.CreateClient()
来创建 HttpClient 实例。
我在 .Net Core 3.1 中这样做
我需要嘲笑这个。根据 以下应该有效...
[Test]
public void Mytest() {
var httpClientFactory = new Mock<IHttpClientFactory>(MockBehavior.Strict);
httpMessageHandler = new Mock<HttpMessageHandler>(MockBehavior.Strict);
httpMessageHandler.Protected()
// Setup the PROTECTED method to mock
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>()
)
// prepare the expected response of the mocked http call
.ReturnsAsync(new HttpResponseMessage()
{
StatusCode = HttpStatusCode.BadRequest,
})
.Verifiable();
var httpClient = new HttpClient(httpMessageHandler.Object);
httpClientFactory.Setup(_ => _.CreateClient()) // This fails
.Returns(httpClient).Verifiable();
systemUnderTest = new MyService(httpClientFactory.Object);
var result = systemUnderTest.MyMethod()
// Assert Stuff
}
但是,当我运行它的时候,报如下...
System.NotSupportedException : Unsupported expression: _ => _.CreateClient()
Extension methods (here: HttpClientFactoryExtensions.CreateClient) may not be used in setup /
verification expressions.
我显然做错了什么,但我看不出是什么。
谁能指点一下?
似乎是因为错误报告“扩展方法不可验证”,在这种情况下,CreateClient 是一个扩展方法,不能对其附加 Verifiable() 调用。
您希望在这里测试什么?您真的需要验证是否调用了 CreateClient(可能不需要)吗?事实上,您是否需要验证是否调用了这些方法中的任何一个?
对我来说,应该编写此测试来检查方法在获得 'Bad request' returned 时的输出。没有必要 'verify' 方法内的调用,因为您开始真正对方法的内部行为进行单元测试,而不是测试该方法的预期输出。
TLDR; 删除验证调用并更改测试以检查预期的 return 行为,而不是添加难以维护的内部实现检查。
IHttpClientFactory
has a single method on it, Create(string)
. It also has an extension method Create(IHttpClientFactory)
that uses the default configuration (it passes Options.DefaultName
).
您不是在模拟接口方法,而是在模拟扩展方法,正如您已经意识到的那样,模拟扩展方法是不可能的。不过别怕,我们有解决办法:模拟界面上实际出现的方法!
您可以模拟所有客户端名称、特定名称或默认 名称 (string.Empty
):
// any name
httpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>()))
.Returns(httpClient).Verifiable();
// specific name
httpClientFactory.Setup(_ => _.CreateClient("SpecificName"))
.Returns(httpClient).Verifiable();
// the default name (extension method invokes this)
httpClientFactory.Setup(_ => _.CreateClient(string.Empty))
.Returns(httpClient).Verifiable();
最后一个选项与调用扩展方法时发生的情况相匹配。但请记住,如果您使用的是 命名客户端 ,您的代码可能会向工厂传递一个名称,而您希望匹配该名称。
如标题所示,我有一些代码调用 IHttpClientFactory.CreateClient()
来创建 HttpClient 实例。
我在 .Net Core 3.1 中这样做
我需要嘲笑这个。根据
[Test]
public void Mytest() {
var httpClientFactory = new Mock<IHttpClientFactory>(MockBehavior.Strict);
httpMessageHandler = new Mock<HttpMessageHandler>(MockBehavior.Strict);
httpMessageHandler.Protected()
// Setup the PROTECTED method to mock
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>()
)
// prepare the expected response of the mocked http call
.ReturnsAsync(new HttpResponseMessage()
{
StatusCode = HttpStatusCode.BadRequest,
})
.Verifiable();
var httpClient = new HttpClient(httpMessageHandler.Object);
httpClientFactory.Setup(_ => _.CreateClient()) // This fails
.Returns(httpClient).Verifiable();
systemUnderTest = new MyService(httpClientFactory.Object);
var result = systemUnderTest.MyMethod()
// Assert Stuff
}
但是,当我运行它的时候,报如下...
System.NotSupportedException : Unsupported expression: _ => _.CreateClient() Extension methods (here: HttpClientFactoryExtensions.CreateClient) may not be used in setup / verification expressions.
我显然做错了什么,但我看不出是什么。
谁能指点一下?
似乎是因为错误报告“扩展方法不可验证”,在这种情况下,CreateClient 是一个扩展方法,不能对其附加 Verifiable() 调用。
您希望在这里测试什么?您真的需要验证是否调用了 CreateClient(可能不需要)吗?事实上,您是否需要验证是否调用了这些方法中的任何一个?
对我来说,应该编写此测试来检查方法在获得 'Bad request' returned 时的输出。没有必要 'verify' 方法内的调用,因为您开始真正对方法的内部行为进行单元测试,而不是测试该方法的预期输出。
TLDR; 删除验证调用并更改测试以检查预期的 return 行为,而不是添加难以维护的内部实现检查。
IHttpClientFactory
has a single method on it, Create(string)
. It also has an extension method Create(IHttpClientFactory)
that uses the default configuration (it passes Options.DefaultName
).
您不是在模拟接口方法,而是在模拟扩展方法,正如您已经意识到的那样,模拟扩展方法是不可能的。不过别怕,我们有解决办法:模拟界面上实际出现的方法!
您可以模拟所有客户端名称、特定名称或默认 名称 (string.Empty
):
// any name
httpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>()))
.Returns(httpClient).Verifiable();
// specific name
httpClientFactory.Setup(_ => _.CreateClient("SpecificName"))
.Returns(httpClient).Verifiable();
// the default name (extension method invokes this)
httpClientFactory.Setup(_ => _.CreateClient(string.Empty))
.Returns(httpClient).Verifiable();
最后一个选项与调用扩展方法时发生的情况相匹配。但请记住,如果您使用的是 命名客户端 ,您的代码可能会向工厂传递一个名称,而您希望匹配该名称。