Skip to content

Integration Test: WebApplicationFactory cannot create custom HttpClient that is registered via IServiceCollection.AddHttpClient<T> #5967

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
PingPongSet opened this issue Dec 19, 2018 · 5 comments
Labels
area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates question
Milestone

Comments

@PingPongSet
Copy link

PingPongSet commented Dec 19, 2018

I register HttpClient via IServiceCollection.AddHttpClient<T>(). However, it seems there is no way to create an HttpClient for T. Because WebApplicationFactory has only CreateClient(); method.

public void ConfigureServices(IServiceCollection services)
{
...
   services.SetWaitAndRetryPolicy<CustomHttpClient>();
}

 public static class IServiceCollectionExtension
    {
        public static void SetWaitAndRetryPolicy<T>(this IServiceCollection services) where T : class
        {
//https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests
            //https://github.com/App-vNext/Polly/wiki/Polly-and-HttpClientFactory            
            Random random = new Random();
            Config config = null;
            services.AddHttpClient<T>((sp, client) => 
                            config = sp.GetService<IOptions<Config>>().Value)                               
                   .AddPolicyHandler((service, request) =>

                        //TransientErrors:
                        //Network failures(System.Net.Http.HttpRequestException)
                        //HTTP 5XX status codes(server errors)
                        //HTTP 408 status code(request timeout)
                        HttpPolicyExtensions.HandleTransientHttpError()

                            //Wait and retry with exponential backoff with Randomisation
                            .WaitAndRetryAsync(config.Retry.RetryCount,
                                retryCount => TimeSpan.FromSeconds(Math.Pow(2, retryCount)) + //2,4,8,...
                                              TimeSpan.FromMilliseconds(random.Next(100, 990)), //random in millisecs
                                onRetry: (outcome, timespan, retryCount, context) =>
                                {
                                    service.GetService<ILog>().Info("Delaying for {delay}ms, then making retry {retry}.",
                                        timespan.TotalMilliseconds, retryCount);
                                }
                            )
                    )
                    .AddPolicyHandler((service, request) =>                      
                            HttpPolicyExtensions.HandleTransientHttpError()
                                //Further external requests are blocked for 30 seconds if five failed attempts occur sequentially.
                                //Circuit breaker policies are stateful.All calls through this client share the same circuit state.
                                .CircuitBreakerAsync(config.CircuitBreaker.HandledEventsAllowedBeforeBreaking,
                                             TimeSpan.FromSeconds(config.CircuitBreaker.DurationOfBreakInSeconds), 
                                             (result, timeSpan, context)=>
                                                    service.GetService<ILog>().Info("CircuitBreaker onBreak for {delay}ms", timeSpan.TotalMilliseconds),
                                              context =>
                                                    service.GetService<ILog>().Info("CircuitBreaker onReset")));


        }
    }

public class HttpClientService
    {
        private readonly HttpClient _client;
        private readonly ILog _logger;

        public HttpClientService(HttpClient client, ILog logger)
        {
            _client = client;
            _logger = logger;
        }

        public async Task<HttpStatusCode> PostAsync(string url, Dictionary<string, string> headers, string body)
        {
            using (var content = new StringContent(body, Encoding.UTF8, "application/json"))
            {
                foreach (var keyValue in headers)
                {
                    content.Headers.Add(keyValue.Key, keyValue.Value);
                }
                var response = await _client.PostAsync(url, content);              
                response.EnsureSuccessStatusCode();
                return response.StatusCode;
            }

        }
    }
@davidfowl
Copy link
Member

What exactly are you trying to do? Write a unit test that uses the HttpClientFactory to talk to the TestServer?

@PingPongSet
Copy link
Author

PingPongSet commented Jan 3, 2019

@davidfowl

Because WebApplicationFactory has only CreateClient(); method, it has not overloads that create a named or typed HttpClient. This allows me to assign Polly polcy to a named or typed HttpClient.

Because I need to test Polly policy showed on the OP.

https://stackoverflow.com/questions/54030145/test-polly-retry-polly-configured-via-startup-configureservices-with-asp-net-c

@Eilon Eilon added the area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates label Jan 3, 2019
@mkArtakMSFT mkArtakMSFT added this to the Discussions milestone Jul 3, 2019
@alexsandro-xpt
Copy link

Any progress about that? I write a intregration test with WebApplicationFactory who it have a service.AddHttpClient<IMySvc, MySvc>() so:

When MySvc do a request with HttpClient httpClient I got a error:
Nenhuma conexão pôde ser feita porque a máquina de destino as recusou ativamente.

InnerException:
SocketErrorCode: ConnectionRefused

What is happen in here? Is this a some kind of limitation or a my bad configuration of WebApplicationFactory?

@danielleiszen
Copy link

Any progress with this? I have the same issue

@ghost
Copy link

ghost commented Dec 7, 2019

Thank you for contacting us. Due to no activity on this issue we're closing it in an effort to keep our backlog clean. If you believe there is a concern related to the ASP.NET Core framework, which hasn't been addressed yet, please file a new issue.

@ghost ghost closed this as completed Dec 7, 2019
@ghost ghost locked as resolved and limited conversation to collaborators Dec 7, 2019
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates question
Projects
None yet
Development

No branches or pull requests

6 participants