簡體   English   中英

如何基於 URL 使用 Moq 對 HttpClient (HttpMessageHandler) 進行單元測試

[英]How to unit test an HttpClient (HttpMessageHandler) with Moq based on the URL

對於開發人員,我會模擬 HttpMessageHandler 來測試 HttpClient,我的問題是如何根據 URL 和 Http 方法進行模擬? 所以響應將是方法和 URL 的函數:

Get + "http://testdoc.com/run?test=true&t2=10   => return X
Get + "http://testdoc.com/walk?test=true&t2=10   => return Y
Post + "http://testdoc.com/walk   => return Z

所有 3 個調用都會返回不同的內容。

我當前的單元測試捕獲了所有內容:

var mockMessageHandler = new Mock<HttpMessageHandler>();
mockMessageHandler.Protected()
    .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
    .ReturnsAsync(new HttpResponseMessage
    {  ... });

謝謝,

問題是您告訴 moq 設置使用任何 http 請求消息: ItExpr.IsAny<HttpRequestMessage>() ,因此對於HttpRequestMessage任何實例,它將始終返回相同的結果。

如果您有不同的 X 個結果,您將需要創建 X 個不同的實例:

string firstUri = "http://testdoc.com/run?test=true&t2=10";
HttpRequestMessage httpRequestMessage_1 = new HttpRequestMessage
{
    RequestUri = new Uri(firstUri),
    Method = ...,
    Content = ...,
};

而不是ItExpr.IsAny<HttpRequestMessage>()httpRequestMessage_1實例,具有:

.Setup<Task<HttpResponseMessage>>("SendAsync", httpRequestMessage_1, ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage
{  /* Something with X */ });

根據你的代碼,我想出了下面的代碼
模擬由其 URL 識別的兩個不同調用。

var mockMessageHandler = new Mock<HttpMessageHandler>();

var content = new HttpContentMock(usersQueryResult);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");

mockMessageHandler.Protected()
  .Setup<Task<HttpResponseMessage>>(
    "SendAsync",
    ItExpr.Is<HttpRequestMessage>(rm => 
      rm.RequestUri.AbsoluteUri.StartsWith("https://example.com/api/users?query=")),
    ItExpr.IsAny<CancellationToken>())
    .ReturnsAsync(
      new HttpResponseMessage
      {
        StatusCode = 200,
        Content = content
      };
    );

mockMessageHandler.Protected()
  .Setup<Task<HttpResponseMessage>>(
    "SendAsync",
    ItExpr.Is<HttpRequestMessage>(rm => 
      rm.RequestUri.AbsoluteUri.StartsWith("https://example.com/api/users/gurka/")),
    ItExpr.IsAny<CancellationToken>())
  .ReturnsAsync(
    new HttpResponseMessage
    {
      StatusCode = 201,
      Content = null, // In reality the user found but we don't care for this test.
    }
  );
}

private class HttpContentMock : HttpContent
{
  private readonly IList<AdUserDataContract> users;
  public HttpContentMock(IList<AdUserDataContract> users)
  {
    this.users = users;  }

  protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
  {
    var json = JsonSerializer.Serialize(users, typeof(AdUsersDataContract));
    var buffer = Encoding.ASCII.GetBytes(json);
    stream.Write(buffer, 0, buffer.Length);
    return Task.CompletedTask;
  }

  protected override bool TryComputeLength(out long length)
  {
    length = 1; // Well... not totally true is it?
    return true;
  }
}

暫無
暫無

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

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