4

I am going to create a new app in Xamarin, and due to demands from the customer, I need to create unit test on almost everything.

In my app I am using a HttpClient, and I have to set Timeout, as the app has to upload images.
But how can I make unit tests for HttpClient.Timeout?

Everything else is mocked up using HttpMessageHandler, but inserting a Task.Delay in there does not affect it.

EDIT
Added code for clarification

public async Task ExecuteAsync_NotExecutedWithinTimeout_ThrowsExecption()
{
   // Arrange
   var endpoint = "http://google.dk/";
   var method = HttpMethod.Get;
   var timeoutClient = TimeSpan.FromMilliseconds(2);
   var timeoutServer = TimeSpan.FromMilliseconds(10);
   var requestor = new Requestor(new MessageHandler { Method = HttpMethod.Get, Timeout = timeoutServer, URL = url });
   bool result = false;

   // Act
   try
   {
      await requestor.ExecuteAsync(method, endpoint, timeout: timeoutClient);
   }
   catch (TimeoutException)
   {
      result = true;
   }

   // Assert
   Assert.AreEqual(true, result);
}

class MessageHandler : HttpMessageHandler
{
   public TimeSpan? TimeOut { get; set; }

   protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   {
      if (Timeout.HasValue)
         await Task.Delay(Timeout.Value);

      return new HttpResponseMessage(System.Net.HttpStatusCode.OK);
   }
}

class Requestor
{
   public async Task<string> ExecuteAsync(HttpMethod httpMethod, string endpoint, TimeSpan? timeout = default(TimeSpan?))
   {
      using (var client = GetHttpClient())
      {
         if (timeout.HasValue)
         {
            client.Timeout = timeout.Value;
         }
         var response = await client.GetAsync(endpoint);
      }
   }
}

private HttpClient GetHttpClient()
{
    var client = _messageHandler == null ? new HttpClient() : new HttpClient(_messageHandler, false);

    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    return client;
}
Lasse Madsen
  • 592
  • 9
  • 30
  • Where is the problem? Can you show us some code? – YuvShap Oct 21 '16 at 09:04
  • I added some of the code now. – Lasse Madsen Oct 21 '16 at 09:17
  • I did not understand how HttpMessageHandler can mock or stub the HttpClient? it's looks like you are using the concrete HttpClient class... – YuvShap Oct 21 '16 at 09:57
  • please refer these questions http://stackoverflow.com/questions/36425008/mocking-httpclient-in-unit-tests http://stackoverflow.com/questions/10693955/stubbing-or-mocking-asp-net-web-api-httpclient – YuvShap Oct 21 '16 at 09:58
  • Sorry, I forgot the GetHttpClient method – Lasse Madsen Oct 21 '16 at 11:07
  • You are using concrete instance of HttpClient class, this makes your code untestable, please refer the links above too see how you can mock the HttpClient class. – YuvShap Oct 21 '16 at 11:11
  • I can get all output from HttpMessageHandler except from TimeoutException, so I do not see any reason to mock it up – Lasse Madsen Oct 21 '16 at 12:17
  • If you want to test the class behavior whaen TimeOutExcpetion occurs you have to mock it, for me this reason is good enough. – YuvShap Oct 21 '16 at 13:11

1 Answers1

5

Instead of

if (Timeout.HasValue)
         await Task.Delay(Timeout.Value);

use

throw new TimeoutException()
Yuri S
  • 5,355
  • 1
  • 15
  • 23