正如标题所示,我有一些代码调用IHttpClientFactory.CreateClient()
创建一个HttpClient实例。
我正在.Net Core 3.1中做到这一点
我需要嘲笑这个。根据{{3}},以下方法应该有效...
[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:不支持的表达式:_ => _.CreateClient() 扩展方法(此处:HttpClientFactoryExtensions.CreateClient)可能无法在安装程序中使用/ 验证表达式。
我显然做错了什么,但我看不出是什么。
任何人都可以提供任何指针吗?
答案 0 :(得分:4)
IHttpClientFactory
上有一个单一方法Create(string)
。它还具有使用默认配置(Create(IHttpClientFactory)
)的扩展方法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();
最后一个选项与调用扩展方法时发生的情况匹配。但是请记住,如果您使用的是命名客户端,则您的代码可能会将名称传递给工厂,并且您希望将其匹配。
答案 1 :(得分:1)
错误报告“扩展方法不可验证”的情况似乎非常多,在这种情况下,CreateClient是扩展方法,不能在其上加上Verifiable()调用。
您希望在这里测试什么?您是否真的需要验证CreateClient是否被调用(可能不会)?确实,您需要验证是否调用了其中任何一种方法吗?
对我来说,应该编写此测试以检查该方法返回“错误请求”时的输出。无需“验证”方法中的调用,因为您开始真正地对方法的内部行为进行单元测试,而不是测试该方法的预期输出。
TLDR; 删除验证调用并更改测试以检查预期的返回行为,而不是添加难以维护的内部实现检查。