0

This is the document https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1 we can see that IHttpClientFactory is registered :

services.AddHttpClient();

and the model class that consume it as:

public BasicUsageModel(IHttpClientFactory clientFactory)
{
   _clientFactory = clientFactory;
}

public async Task OnGet()
{
   ...
   var client = _clientFactory.CreateClient();
   var response = await client.SendAsync(request);
   ...
}

but how about we don't register it, and we just create a new instance of it as:

public async Task OnGet()
{
   ...
   var client = new HttpClient();
   var response = await client.SendAsync(request);
   ...
}

so that the BasicUsageModel's constructor doesn't need to take any argument, and when do unit testing , I don't need to use Moq to mock it, isn't that ever better?

and for the first case, how can I mock the IHttpClientFactory to test OnGet() without actually send a request?

amjad
  • 3,048
  • 1
  • 11
  • 42
  • but your unit test will actually make an `http` request? thats probably what you dont want – Ric Jan 15 '20 at 10:59
  • In neither case you are mocking it. Also it does two different things, the client factory does pool the httpclient handlers, `new`ing `HttpClient` doesn't. https://josefottosson.se/you-are-probably-still-using-httpclient-wrong-and-it-is-destabilizing-your-software/ – Tseng Jan 15 '20 at 11:02
  • 1
    The purpose of not creating the client manually is to avoid socket exhaustion. The factory manages the client connections to avoid destabilizing your application Reference [You're using HttpClient wrong](https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/) – Nkosi Jan 15 '20 at 11:02
  • Here is a more recent article on the topic Reference [You're (probably still) using HttpClient wrong and it is destabilizing your software](https://josefottosson.se/you-are-probably-still-using-httpclient-wrong-and-it-is-destabilizing-your-software/) – Nkosi Jan 15 '20 at 11:04

2 Answers2

0

when do unit testing , I don't need to use Moq to mock it, isn't that ever better

No it's not. The whole point of a unit test is to test the unit without it's dependencies. In this case, without an actual server to connect to.

Assuming you have one unit test for your client actually getting the data and one unit test for when your client fails to get the data, there is no way you can reasonably do that with your way.

You need to mock it to be able to have multiple test-cases for the different outcomes of your http call.

nvoigt
  • 68,786
  • 25
  • 88
  • 134
  • thanks for the answer. so how can I mock it ? I have to mock the `CreateClient()` method? – amjad Jan 15 '20 at 11:11
  • Unit testing is done via `HttpMessageHandler`. See [this answer](https://stackoverflow.com/a/36427274/455493) – Tseng Jan 15 '20 at 14:49
0

Quite aside from the UnitTesting point already raised, the document you linked specifies one of the main reasons to use the IHttpClientFactory over instatiating a new HttpClient directly:

Manages the pooling and lifetime of underlying HttpClientMessageHandler instances. Automatic management avoids common DNS (Domain Name System) problems that occur when manually managing HttpClient lifetimes.

Jamiec
  • 128,537
  • 12
  • 134
  • 188