簡體   English   中英

單元測試 HttpClient 時如何模擬 GetDiscoveryDocumentAsync?

[英]How to Mock GetDiscoveryDocumentAsync When Unit Testing HttpClient?

我正在嘗試為 HttpClient 服務編寫一些單元測試,並且在嘗試模擬 GetAccessToken() function 中的部分代碼時遇到了問題。

該服務接受一個 IHttpClientFactory。 從到目前為止我所做的閱讀看來,要正確地模擬這個,我必須模擬 IHttpClientFactory,讓它返回一個依賴於模擬 HttpMessageHandler 的新 HttpClient,我這樣做是這樣的:

var mockHttpClientFactory = new Mock<IHttpClientFactory>();

var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
mockHttpMessageHandler.Protected()
    .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
    .ReturnsAsync(new HttpResponseMessage
        {
         StatusCode = HttpStatusCode.OK,
         Content = new StringContent("{'name':thecodebuzz,'city':'USA'}"),
        });

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

_httpClientService = new HttpClientService(mockHttpClientFactory.Object, mockConfig.Object); 

這方面有效,我已經能夠調用 CreateClient() 工作正常。 然而,function 我正在嘗試測試調用我的 GetAccessToken() function,然后調用 client.GetDiscoveryAccessToken()。 我猜 GetDiscoveryAccessToken() function 需要被嘲笑,但我不確定如何繼續。

我嘗試使用模擬方法創建客戶端模擬,並在調用 CreateClient 時返回它,如下所示:

 var discoDoc = // Mocked disco doc code;

 var client = new Mock<HttpClient>(mockHttpMessageHandler.Object);
 client.Setup(x => x.GetDiscoveryDocumentAsync(It.IsAny<string>())).Returns(discoDoc);

 mockHttpClientFactory.Setup(x => x.CreateClient(It.IsAny<string>())).Returns(client);

 _httpClientService = new HttpClientService(mockHttpClientFactory.Object, mockConfig.Object);

不幸的是,我在告訴 CreateClient function 要返回什么的行上收到此錯誤:“無法從 'Moq.Mock' 轉換為 'System.Net.Http.HttpClient'”。 我猜這是因為我需要返回一個真正的 HttpClient 而不是一個 Mocked 。

關於我可以從這里 go 到哪里的任何想法?

您快到了,對於 CreateClient,您將返回 Moq 的 Object,而不是 Mocked object。 只需要返回模擬的 object 如下。

 var discoDoc = // Mocked disco doc code;

 var client = new Mock<HttpClient>(mockHttpMessageHandler.Object);
 client.Setup(x => x.GetDiscoveryDocumentAsync(It.IsAny<string>())).Returns(discoDoc);

 mockHttpClientFactory.Setup(x => x.CreateClient(It.IsAny<string>())).Returns(client.Object);

 _httpClientService = new HttpClientService(mockHttpClientFactory.Object, mockConfig.Object);

讓我知道這是否是您所期望的。

實際上沒有辦法嘲笑這一點。 對此進行測試的唯一方法是以與 IdentityModel 團隊類似的方式進行 - 使用他們自己的 HttpMessageHandler 實現。 NetworkHandler )然后您可以執行以下操作:

HttpResponseMessage GetDiscoveryResponse()
{
    var wellKnown = File.ReadAllText("openid-configuration.json");
    var response = new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new StringContent(wellKnown)
    };
    return response;
};
var httpClient = new HttpClient(new NetworkHandler(request => {
    if (request.RequestUri.AbsoluteUri.Contains("openid-configuration"))
    {
        return GetDiscoveryResponse();
    }
    throw new NotImplementedException();
}));

暫無
暫無

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

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