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
IHttpClientFactoryto create a named client then change theSetupto 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>());

