4

I wants unit test the Search class below that uses HttpClient,

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

Is there a way to mock the HttpClient? I cannot find any information via Google.

Update

Is there an alternaitve to sending an Http web request that can be mocked. I have the code below:

 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);
          ///...
}
Pingpong
  • 7,681
  • 21
  • 83
  • 209
  • Hmm, do you really want to mock a part of the framework? I don't see how this would gain you anything, but perhaps I'm just missing your point. – David L Mar 10 '13 at 18:54

2 Answers2

3

In .Net 4.5 framework you can do this.

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
}
Manjay_TBAG
  • 2,176
  • 3
  • 23
  • 43
2

You can't mock it with a mocking framework like Rhino-Mocks, because in order to do that you need either an interface or virtual methods on the HttpClient class. A mocking framework will create a mock for you, that either implements the methods defined on the interface or overrides the methods of your virtual class.

So either you wrap the HttpClient class and let it implement an interface, or, don't mock it.

If you'd change your code to something like this:

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);
        // ...
    }
}

If you create a class that implements the IWebRequestCreator then you'd be able to mock the functionality. The implementing class would just call WebRequest.Create(queryUrl);

bas
  • 13,550
  • 20
  • 69
  • 146
  • 1
    Yeah, wrap it :). Not sure how your caller of `Search` is defined, but maybe you can steal some ideas from this post: http://stackoverflow.com/questions/9823039/is-it-possible-to-mock-out-a-net-httpwebresponse – bas Mar 10 '13 at 20:05
  • @Pingpong made an update according to your update in your question – bas Mar 10 '13 at 20:12