iT邦幫忙

2022 iThome 鐵人賽

DAY 29
0
Software Development

.net6套件入門系列 第 29

[.net 6] HttpClient單元測試範例

  • 分享至 

  • xImage
  •  

目的

面試的時候被問到要如何做包含外部api的單元測試問題,稍微查一下其實很簡單,怎麼當下答不出來呢?
主要有兩種方式,一種為.net core 2.1以後有提供IHttpClientFactory的介面可以使用。

同步更新於個人部落格
HttpClient單元測試範例

1.建立新專案

選擇ASP.NET Core Web API專案範本,並執行下一步
步驟一

2.設定新的專案

命名你的專案名稱,並選擇專案要存放的位置。
步驟二

3.其他資訊

直接進行下一步
步驟三

4.建立資料夾

步驟四

5.編輯Program.cs檔案

註冊AddHttpClient。

builder.Services.AddHttpClient();

步驟五

6.新增一個類別檔

  • 加入前
    步驟6-1
  • 加入後
    步驟6-2

7.建構子注入

將註冊的httpclient透過建構子注入

    readonly IHttpClientFactory _httpClientFactory;
    public CallAPIServices(IHttpClientFactory httpClientFactory) {
      _httpClientFactory = httpClientFactory;
    }
  • 加入前
    步驟7-1
  • 加入後
    步驟7-2

8.新增方法

新增一個會去發外部請求的方法,模擬當有包含第三方api時如何測試

    public async Task<string> Get() {
      var client = _httpClientFactory.CreateClient();
      var response = await client.GetAsync("https://example.com");
      if (response.IsSuccessStatusCode) {
        var responseString = await response.Content.ReadAsStringAsync();
        return responseString;
      }
      return "";
    }

步驟8

9.新增測試專案

對方案點選右鍵>加入>新增專案

步驟9

10.設定新的專案

替測試專案命名,建議命名規則以.Tests做結尾
步驟10

11.其他資訊

專案架構需要與要測試的專案相同
步驟11

12.加入參考

將要測試的專案加入測試專案

對CallAPIServices.Tests點選右鍵>加入>專案參考

步驟12

13.NuGet加入套件

透過NuGet安裝Moq套件至測試專案
步驟13

14.新增對應資料夾與測試檔案

新增檔案,檔名需要與要測試的檔案一致,並加上Tests
步驟14

15.新增程式碼

在新增的檔案內新增一個方法並寫入程式碼,一開始會看到許多紅色波浪,是因為沒有加入參考

    //定義這個方法是不需要傳入參數的單元測試,另一種為[Theory],詳細說明可看相關參考5
    [Fact]
    //命名規則 => 類別名稱_方法名稱_要測試的方法行為_回傳狀態
    public async Task CallAPIServices_Get_HttpClient_Success() {
      //模擬出一個IHttpClientFactory的假物件
      var mockFactory = new Mock<IHttpClientFactory>();
      //產生http回傳的實例
      HttpResponseMessage result = new HttpResponseMessage() {
        StatusCode = HttpStatusCode.OK,
        Content = new StringContent("{'account':'bill','age':18}")
      };
      //模擬出一個http處理程序的基本類型實例的假物件
      var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
      //模擬http發出請求後所做的一連串事情,最後並回傳結果
      //protected => 發出請求的方法SendAsync是一個protected存取修飾詞,不能直接存取,所以告訴moq請幫忙執行protected方法,詳細說明可看參考6
      //Setup => 設定此執行動作為SendAsync方法,並需要兩個傳入參數,HttpRequestMessage與CancellationToken
      //ItExpr.IsAny => 請moq協助傳入一個參數為HttpRequestMessage與CancellationToken的假參數,另一種為It.IsAny是非protected方法使用
      //ReturnsAsync => 回傳非同步的值
      mockHttpMessageHandler.Protected()
          .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
          .ReturnsAsync(result);
      //將製作好的假請求與回傳給HttpClient
      var client = new HttpClient(mockHttpMessageHandler.Object);
      //模擬實際請求,並接收到我們所製作的假物件
      mockFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(client);
      //將製作好的完整請求流程給我們在使用的方法
      var services = new HttpclientExample.Services.CallAPIServices(mockFactory.Object);
      //執行要測試的方法
      var response = await services.Get();
      //回傳值不能為null
      Assert.NotNull(response);
      //回傳值必須一致
      Assert.Equal("{'account':'bill','age':18}", response);
    }
  • 加入前
    步驟15-1

步驟15-2

  • 加入後
    步驟15-3

步驟15-4

16.執行測試

點右鍵執行測試,最後結果會如左下角顯示成功
步驟16

相關參考

單元測試好的做法
為什麼要使用IHttpClientFactory
moq套件介紹
單元測試介紹
Fact跟Theory差別
存取修飾詞

範例檔

GitHub


上一篇
[.net 6] Moq範例
下一篇
[.net 6] 後記
系列文
.net6套件入門30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言