【发布时间】:2019-10-26 01:42:08
【问题描述】:
我正在处理一段看起来像这样的代码:
public class Uploader : IUploader
{
public Uploader()
{
// assign member variables to dependency injected interface implementations
}
public async Task<string> Upload(string url, string data)
{
HttpResponseMessage result;
try
{
var handler = new HttpClientHandler();
var client = new HttpClient(handler);
result = await client.PostAsync(url, new FormUrlEncodedContent(data));
if (result.StatusCode != HttpStatusCode.OK)
{
return "Some Error Message";
}
else
{
return null; // Success!
}
}
catch (Exception ex)
{
// do some fancy stuff here
}
}
}
我正在尝试对Upload 函数进行单元测试。特别是,我需要模拟HttpClient。在阅读了此处的其他答案和 these two 文章后,我知道解决此问题的更好方法之一是模拟 HttpMessageHandler 并将其传递给 HttpClient 并让它返回我想要的任何内容。
所以,我首先在构造函数中传入HttpClient 作为依赖项:
public class Uploader : IUploader
{
private readonly HttpClient m_httpClient; // made this a member variable
public Uploader(HttpClient httpClient) // dependency inject this
{
m_httpClient = httpClient;
}
public async Task<string> Upload(string url, string data)
{
HttpResponseMessage result;
try
{
var handler = new HttpClientHandler();
result = await m_httpClient.PostAsync(url, new FormUrlEncodedContent(data));
if (result.StatusCode != HttpStatusCode.OK)
{
return "Some Error Message";
}
else
{
return null; // Success!
}
}
catch (Exception ex)
{
// do some fancy stuff here
}
}
}
并将:services.AddSingleton<HttpClient>(); 添加到 Startup.cs 的 ConfigureServices 方法中。
但是现在我面临一个小问题,原始代码专门创建了一个 HttpClientHandler 来传递。那么我该如何重构它以接受一个可模拟的处理程序?
【问题讨论】:
-
如果使用 asp.net core,请阅读 HttpClientFactory
-
HttpClient 将所有调用委托给 HttpClientHandler。要模拟 HttpClient,请使用模拟处理程序。您可以通过使用 HttpClientFactory 并在测试中指定模拟处理程序来自动执行此操作
标签: c# .net unit-testing .net-core dotnet-httpclient