簡體   English   中英

單元測試 HTTP 客戶端

[英]Unit testing HTTP Client

我有以下使用 HttpClient 的代碼。 我是 C# 新手,想學習如何對我的 HttpClient 進行單元測試,但不確定從哪里開始。 這是我的代碼:

 protected override async Task PopulateData()
        {
            using (var client = new HttpClient())
            {
                var token = "private token";
                var requestUrl = api_url_here;
                var authenticatedRequestUrl = requestUrl + $"{token}";
                var response = await client.GetAsync(authenticatedRequestUrl);
                var stringResult = await response.Content.ReadAsStringAsync();

                // do something
            }
        }

我看過很多不同的文章,提出了不同的單元測試方法,但我不確定如何正確使用它們。 例如,我在很多網站上都看到過這個單元測試模式:

  [Test]
        public async Task MockingHTTP()
        {
            var requestUri = new Uri("");
            var expectedResponse = "Response";
            var mockHandler = new Mock<HttpMessageHandler>();

            mockHandler.Protected()
                .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
                ItExpr.IsAny<CancellationToken>())
                .ReturnsAsync(new HttpResponseMessage(Net.HttpStatusCode.OK));

            var httpClient = new HttpClient(mockHandler.Object);
            var result = await httpClient.GetStringAsync(requestUri).ConfigureAwait(false);
            Assert.AreEqual(expectedResponse, result);

            }
        }

但是我不知道如何將這種方法應用於我的代碼。 請有人指出我的正確方向以成功對 HttpClient 進行單元測試嗎?

單元測試時要做的第一件事是確定您的“被測系統”或 SUT。 這就是您需要驗證其行為的事情。 您的 SUT 的任何依賴項都應該被模擬,您不應該使用真實版本。

在這種情況下,您使用的是 HttpClient,但您無法在方法中使用不同的處理程序。 使用不同的處理程序是偽造 HttpClient 響應的最簡單方法。 HttpClient 通過構造函數接受不同的處理程序。 所以你需要像這樣調整你的代碼:

public class YourClassName
{
    private readonly HttpMessageHandler _httpMessageHandler;

    public YourClassName(HttpMessageHandler httpMessageHandler)
    {
        _httpMessageHandler = httpMessageHandler;
    }

    protected override async Task PopulateData()
    {
        using (var client = new HttpClient(_httpMessageHandler))
        {
            var token = "private token";
            var requestUrl = api_url_here;
            var authenticatedRequestUrl = requestUrl + $"{token}";
            var response = await client.GetAsync(authenticatedRequestUrl);
            var stringResult = await response.Content.ReadAsStringAsync();

            // do something
        }
    }
}

現在它是單元可測試的,因為您可以模擬 HttpMessageHandler。 但是執行此操作的代碼很麻煩 考慮到您在使用 HttpClient 時遇到的其他缺陷,最好一開始甚至不使用 HttpClient。 看:

我的團隊所做的是改用Flurl 它有一個更好的語法,沒有 HttpClient 具有的 IDisposable 的奇怪特性,並且易於單元測試。

protected override async Task PopulateData()
{
    var token = "private token";
    var requestUrl = api_url_here;
    var authenticatedRequestUrl = requestUrl + $"{token}";
    var stringResult = authenticatedRequestUrl.
    var response = await authenticatedRequestUrl.GetAsync();
    var stringResult = await response.Content.ReadAsStringAsync();

    // do something
}

然后你的單元測試變得簡單得多:

[Test]
public async Task PopulateDataTest()
{
    var requestUri = new Uri("SomeUriWithAToken");
    var expectedResponse = "some response body";
    var systemUnderTest = new YourClassName();

    using (var httpTest = new HttpTest())
    {
        httpTest.RespondWith(expectedResponse);
        var result = await systemUnderTest.PopulateData();
        Assert.AreEqual(expectedResponse, result);
        httpTest.ShouldHaveCalled(requestUri);
    }
}

Flurl 的文檔很棒。 您可以讓它返回各種響應,甚至可以自動將響應反序列化到 C# 類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM