在Xunit测试中使用Moq库模拟HttpClient GetAsync [英] Mocking HttpClient GetAsync by using Moq library in Xunit test

查看:94
本文介绍了在Xunit测试中使用Moq库模拟HttpClient GetAsync的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为这个小型服务编写一个简单的单元测试,它只需调用外部API:

I am writing a simple unit test for this small service that simply calls external APIs:

public class ApiCaller : IApiCaller
{
    private readonly IHttpClientFactory _httpFactory;

    public ApiCaller(IHttpClientFactory httpFactory)
    {
        _httpFactory = httpFactory;
    }

    public async Task<T> GetResponseAsync<T>(Uri url)
    {
        using (HttpClient client = _httpFactory.CreateClient())
        {
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.Timeout = TimeSpan.FromSeconds(20);
            using (HttpResponseMessage response = await client.GetAsync(url))
            {
                response.EnsureSuccessStatusCode();
                string responseBody = await response.Content.ReadAsStringAsync();

                return JsonConvert.DeserializeObject<T>(responseBody);
            }

        }
    }
}

我的第一个问题是:嘲笑似乎不是很常见的做法,因此测试了这些服务,我想知道是否有一些具体的解释.

My first question is: it doesn't seem to be very common practice mocking and therefore testing such services and I am wondering if there is some specific explanation.

第二,我试图编写一个简单的单元测试,但是由于HttpClient没有实现任何接口,所以我无法模拟 GetAsync 调用.

Second, I tried to write a simple unit test but I cannot Mock the GetAsync call since HttpClient doesn't implement any interface.

public class ApiCallerTest
{
    private readonly ApiCaller _target;
    private readonly Mock<IHttpClientFactory> _httpClientFactory;


    public ApiCallerTest()
    {
        _httpClientFactory = new Mock<IHttpClientFactory>();
        _target = new ApiCaller(_httpClientFactory.Object);
    }

    [Fact]
    public void WhenACorrectUrlIsProvided_ServiceShouldReturn()
    {


        var client = new HttpClient();
        _httpClientFactory.Setup(x => x.CreateClient(It.IsAny<string>())).Returns(client);

        var httpMessageHandler = new Mock<HttpMessageHandler>();

    }

}

推荐答案

无论您使用的HttpClient类(GetAsync,PostAsync等)中的方法如何,下面的代码都是您应使用的代码.所有这些方法都是为了方便程序员而创建的.他们所做的是使用HttpMessageHandler类的 SendAsync 方法.

The code below is what you should use regardless of the method in the HttpClient class you use (GetAsync, PostAsync, etc.). All these methods are created for the convenience of the programmer. What they do is use the SendAsync method of the HttpMessageHandler class.

var mockHttpMessageHandler = new Mock<HttpMessageHandler>();

// Setup Protected method on HttpMessageHandler mock.
mockHttpMessageHandler.Protected()
    .Setup<Task<HttpResponseMessage>>(
        "SendAsync",
        ItExpr.IsAny<HttpRequestMessage>(),
        ItExpr.IsAny<CancellationToken>()
    )
    .ReturnsAsync((HttpRequestMessage request, CancellationToken token) =>
    {
        HttpResponseMessage response = new HttpResponseMessage();

        // configure your response here

        return response;
    });

然后使用这种方式:

var httpClient = new HttpClient(mockHttpMessageHandler.Object);
var result = await httpClient.GetAsync(url, cancellationToken);

您还可以在此处查看如何为httpclient创建模拟getasync方法?

这篇关于在Xunit测试中使用Moq库模拟HttpClient GetAsync的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆