【问题标题】:Unit test a class that uses HttpClient in System.Net.Http v4在 System.Net.Http v4 中对使用 HttpClient 的类进行单元测试
【发布时间】:2013-02-25 21:28:57
【问题描述】:

我想对下面使用 HttpClient 的 Search 类进行单元测试,

public class Search:ISearch{
HttpClient httpClient;
  public Search(HttpClient httpClient){
   this.httpClient = httpClient;
}
   //use httClient to send request.
}

有没有办法模拟 HttpClient?我无法通过 Google 找到任何信息。

更新

发送可以模拟的 Http Web 请求是否有替代方法。我有以下代码:

 public class Search:ISearch{
private static readonly string url = "http://www.google.com/search";
public Result SendSearch(string query){
           string queryUrl = string.Format("{0}?q={1}", url, query);
           var webRequest = WebRequest.Create(queryUrl);
          ///...
}

【问题讨论】:

  • 嗯,你真的想模拟框架的一部分吗?我看不出这会给你带来什么好处,但也许我只是错过了你的意思。

标签: c# unit-testing mocking


【解决方案1】:

在 .Net 4.5 框架中,您可以做到这一点。

public class FakeHttpMessageHandler : HttpMessageHandler
{
    private HttpResponseMessage response;

    public FakeHttpMessageHandler(HttpResponseMessage response)
    {
        this.response = response;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var responseTask =  new TaskCompletionSource<HttpResponseMessage>();
        responseTask.SetResult(response);

        return responseTask.Task;
    }
}


[TestMethod]
public void TestGetContents()
{
    var responseMessage = new HttpResponseMessage();
    var messageHandler = new FakeHttpMessageHandler(responseMessage);
    var client = new HttpClient(messageHandler);
    var sut = new Search(client);

    sut.SendSearch("urQuery");

    // Asserts
}

【讨论】:

    【解决方案2】:

    你不能用像 Rhino-Mocks 这样的模拟框架来模拟它,因为为了做到这一点,你需要 HttpClient 类上的 interfacevirtual methods。模拟框架将为您创建一个模拟,它要么实现接口上定义的方法,要么覆盖虚拟类的方法。

    所以要么包装HttpClient 类并让它实现一个接口,要么不要模拟它。

    如果您将代码更改为以下内容:

    public class Search:ISearch
    {
        private static readonly string url = "http://www.google.com/search";
        private readonly IWebRequestCreator _generator;
    
        public Search(IWebRequestCreator generator)
        {
            _generator = generator;
        }
    
        public Result SendSearch(string query)
        {
            var queryUrl = string.Format("{0}?q={1}", url, query);
            var webRequest = _generator.Create(queryUrl);
            // ...
        }
    }
    

    如果您创建一个实现IWebRequestCreator 的类,那么您就可以模拟该功能。实现类只需调用WebRequest.Create(queryUrl);

    【讨论】:

    • 是的,把它包起来:)。不确定你的Search 的调用者是如何定义的,但也许你可以从这篇文章中窃取一些想法:stackoverflow.com/questions/9823039/…
    • @Pingpong 根据您在问题中的更新进行了更新
    猜你喜欢
    • 1970-01-01
    • 2017-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多