模拟使用 IHttpClientFactory.CreateClient 创建的 HttpClient

Stu*_*ing 3 c# unit-testing httpclientfactory

正如标题所暗示的,我有一些代码可以调用IHttpClientFactory.CreateClient()来创建一个 HttpClient 实例。

我在 .Net Core 3.1 中这样做

我需要嘲笑这个。根据这个问题“C# Mock IHttpclient & CreateClient”,以下应该有效......

[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
}
Run Code Online (Sandbox Code Playgroud)

但是,当我运行它时,会报告以下内容...

System.NotSupportedException:不支持的表达式:_ => _.CreateClient() 扩展方法(此处:HttpClientFactoryExtensions.CreateClient)不能用于设置/验证表达式。

我显然做错了什么,但我看不出是什么。

任何人都可以提供任何指示吗?

pin*_*x33 5

IHttpClientFactory有一个方法,Create(string). 它还有一个Create(IHttpClientFactory)使用默认配置的扩展方法(它通过Options.DefaultName)。

您不是在模拟接口方法,而是在模拟扩展方法,正如您已经意识到的那样,模拟扩展方法是不可能的。但是不要害怕,我们有一个解决方案:mock 实际出现在界面上的方法!

您可以为所有客户端名称、特定名称或默认名称 ( 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();
Run Code Online (Sandbox Code Playgroud)

最后一个选项与调用扩展方法时发生的情况相匹配。但请记住,如果您使用命名客户端,您的代码可能会将名称传递给工厂,并且您希望与之匹配。