I have a class that uses the HttpClient to send a request, and get a response, but I use the HttpClient directly and this doesn't lend itself well to unit testing, what I want to do is to create a custom HttpMessageHandler and pass it to HttpClient to handle my requests, and when I wanted to unit test the method, stub the custom handler to return some fake response, here is the dependent class (note that I removed the extraneous data):
public class CaptchaValidator : ICaptchaValidator
{
public async Task<CaptchaResponse> ValidateCaptchaAsync(string secret)
{
using (var client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync($"recaptcha/api/siteverify?secret={secret}&response={answer}");
}
}
}
My end goal is to have a private field for HttpMessageHandler and pass it to the HttpClient to handle my real requests, and when I wanted to test it, I fake the custom HttpMessageHandler to not go across the wire and instead return some stubbed data.
This is somewhat unrelated to the main question, but I think it may clarify what I want to achieve if I include my test method, assume I have introduced a field of type HttpMessageHandler:
private readonly HttpMessageHandler _httpMessageHandler;
public CaptchaValidator(IHttpContextAccessor contextAccessor, HttpMessageHandler httpMessageHandler)
{
_contextAccessor = contextAccessor;
_httpMessageHandler = httpMessageHandler;
}
And I've used it in HttpClient:
using (var client = new HttpClient(_httpMessageHandler))
Now I can write my test like:
[Fact]
public async Task ValidateCaptchaAsync_ShouldReturn_TheCorrectType()
{
_httpMessageHandler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content =
new StringContent(
"{\"success\": false,\"error-codes\": [\"It's a fake error!\",\"It's a fake error\"]}")
});
var sut = new CaptchaValidator(_contextAccessor.Object, _httpMessageHandler.Object);
//Act
var result = await sut.ValidateCaptchaAsync("dummy-secret");
//Assert
result.Should().BeOfType<CaptchaResponse>();
}
But so far, I was unsuccessful in creating a custom HttpMessageHandler and passing it to my container to resolve the HttpMessageHandler, I've tried the approaches suggested in these questions:
How to resolve Web API Message Handler / DelegatingHandler from IoC container on each request
How to implement HttpMessageHandler in Web API?
As you can see the questions are asked in the context of Web Api, I was wondering if there is a way to do this in Asp.Net Core?
Aucun commentaire:
Enregistrer un commentaire