dimanche 11 septembre 2016

How to Implement HttpMessageHandler In Asp.Net Core

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