簡體   English   中英

如何編寫單元測試用例 IHttpClientFactory

[英]How to write unit test case IHttpClientFactory

我在服務層中有一個方法可以連接到服務,並且我正在使用IHttpClientFactory 我的方法工作正常。 現在我正在嘗試為此編寫單元測試用例。

public async Task<MyObject> MyMethodAsync(string arg1, string arg2)
{
    var client = _httpClientFactory.CreateClient("XYZ");

    var Authkey = "abc"; 
    var AuthToken = "def";
       
    var headers = new Dictionary<string, string>
        {
            { Authkey,AuthToken }
        };

    client.AddTokenToHeader(headers); //This method set  the DefaultRequestheader from the dictionary object

    var reqData = new
    {
        prop1 = "X", 
        prop2 = "Y"
    };//req object

    var content = new StringContent(JsonConvert.SerializeObject(reqData), Encoding.UTF8, "application/json");

    //This is httpClient Post call for posting data 
    HttpResponseMessage response = await client.PostAsync("postData", content); 
    if (!response.IsSuccessStatusCode || response.Content == null)
    {
        return null;
    }

    MyObject myObject = JsonConvert.DeserializeObject<MyObject>(response.Content.ReadAsStringAsync().Result);//read the result to an object
    return myObject;
}

對於上述方法,我正在編寫測試用例。 在這里,我嘗試將 Post 方法設置為 OK,並期望MyMethodAsync方法為 true,因為PostAsync為 true。 在這里我遇到了一個例外

System.InvalidOperationException:提供了無效的請求 URI。 請求 URI 必須是絕對 URI,或者必須設置 BaseAddress。

[Test]
public async Task MyMethodAsync_Gets_True()
{
    var response = new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new StringContent("It worked!")
    };

    //Mock the httpclientfactory
    var _httpMessageHandler = new Mock<HttpMessageHandler>();
    var mockFactory = new Mock<IHttpClientFactory>(); 

    //Specify here the http method as post
    _httpMessageHandler.Protected()
      .Setup<Task<HttpResponseMessage>>("SendAsync",
       ItExpr.Is<HttpRequestMessage>(req => req.Method == HttpMethod.Post),
       ItExpr.IsAny<CancellationToken>())
       .ReturnsAsync(new HttpResponseMessage
       {
           StatusCode = HttpStatusCode.OK
       });


    var httpClient = new HttpClient(_httpMessageHandler.Object);
    mockFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);

    var arg1 = "X";
    var arg2 = "D101";

    var service = new MyService(_mockAppSettings.Object, mockFactory.Object);
    var result = await service.MyMethodAsync(arg1, arg2);
    // Assert
    Assert.IsNotNull(result);
}

有人可以顯示我在這里犯了什么錯誤嗎?

正如例外所說,你必須

  • 要么用絕對 url 調用PostAsync
  • 或者設置 HttpClient 的BaseAddress

如果您選擇第二個,您需要做的就是:

var httpClient = new HttpClient(_httpMessageHandler.Object);

httpClient.BaseAddress = new Uri("http://nonexisting.domain"); //New code

mockFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient);

通過此修改,異常將消失。
但是您的測試將失敗,因為response.Content將是null ,這就是MyMethodAsync將返回null的原因。

要解決此問題,讓我們將設置更改為:

public static async Task MyMethodAsync_Gets_True()
{
    //Arrange
    MyObject resultObject = new MyObject();
    var response = new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new StringContent(JsonConvert.SerializeObject(resultObject))
    };

    var _httpMessageHandler = new Mock<HttpMessageHandler>();
    _httpMessageHandler.Protected()
        .Setup<Task<HttpResponseMessage>>("SendAsync",
          ItExpr.Is<HttpRequestMessage>(req => req.Method == HttpMethod.Post),
          ItExpr.IsAny<CancellationToken>())
        .ReturnsAsync(response);
    ...

    //Act
    var result = await service.MyMethodAsync(arg1, arg2);

    //Assert
    Assert.NotNull(result);
}

暫無
暫無

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

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