I am using a .NET 6 Web API controller with IHttpClientFactory to perform external API calls. As such, I have the following constructor:
public MyController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
This works because in my Program.cs
I add an HTTP Client to my builder.Services
.
In my tests, how do I instantiate/set up the httpClientFactory
for the controller because I need it to instantiate my controller: var controller = new MyController(httpClientFactory);
generates an error since there isn't any settings added.
I ran into a similar issue with configurations from appsettings.json and resolved with ConfigurationBuilder
but there doesn't seem to be a similar one for IHttpClientFactory
.
If you need any more information, please let me know. Thanks!
CodePudding user response:
I tried as below:
[TestFixture]
public class IndexActionTests
{
private HomeController controller;
[SetUp]
public void Setup()
{
var services = new ServiceCollection();
services.AddHttpClient();
var provider = services.BuildServiceProvider();
var httpclientfactory = provider.GetService<IHttpClientFactory>();
controller = new HomeController(httpclientfactory);
}
[Test]
public void Test1()
{
var result = controller.Index();
Assert.AreEqual(typeof(ViewResult),result.GetType());
}
}
Result:
CodePudding user response:
In order to be able to use a properly mocked IHttpClientFactory
in your unit test you need to do the following steps:
Setup a DelegatingHandler
mock
var mockHandler = new Mock<DelegatingHandler>();
mockHandler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", It.IsAny<HttpRequestMessage>(), It.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK))
.Verifiable();
mockHandler.As<IDisposable>().Setup(s => s.Dispose());
This sample mock will always return with 200 OK status code and without a response body
- Tailor the setup for your needs
Create an HttpClient
var httpClient = new HttpClient(mockHandler.Object);
It creates an HttpClient
instance and pass the above handler to it
Setup an IHttpClientFactory
mock
var mockFactory = new Mock<IHttpClientFactory>(MockBehavior.Strict);
mockFactory
.Setup(factory => factory.CreateClient())
.Returns(httpClient)
.Verifiable();
It setups an IHttpClientFactory
mock to return the above HttpClient
for the CreateClient
method call
- If you use the
IHttpClientFactory
to create a named client then change theSetup
to this.Setup(factory => factory.CreateClient(It.IsAny<string>()))
Use the mock objects for verification
mockFactory.Verify(factory => factory.CreateClient(), Times.Once);
mockHandler.Protected()
.Verify("SendAsync", Times.Once(), It.IsAny<HttpRequestMessage>(), It.IsAny<CancellationToken>());