Pingpong
Pingpong

Reputation: 8019

Unit test a class that uses HttpClient in System.Net.Http v4

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

Upvotes: 4

Views: 2649

Answers (2)

Manjay_TBAG
Manjay_TBAG

Reputation: 2245

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
}

Upvotes: 3

bas
bas

Reputation: 14982

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);

Upvotes: 2

Related Questions