question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

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

See original GitHub issue

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;
            }

        }
    }

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:1
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
danielleiszencommented, Nov 4, 2019

Any progress with this? I have the same issue

0reactions
msftbot[bot]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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

HTTP client and HTTP client factory in integration testing
I limited myself to showing how to use the WebApplicationFactory<T> shipped in the Microsoft.AspNetCore.Mvc.Testing package. Are we done? I'm ...
Read more >
c# - WebApplicationFactory is running the Api with the old ...
I'm working on an integration test for a Web API which communicates through Redis, so I tried to replace the Redis Server with...
Read more >
Integration tests in ASP.NET Core
Customize WebApplicationFactory. Web host configuration can be created independently of the test classes by inheriting from ...
Read more >
Supporting integration tests with WebApplicationFactory in ...
In this post I look at a related change to ensure that integration testing with WebApplicationFactory works in .NET 6.
Read more >
Mocking dependencies in ASP.NET Core tests
In this article, I'll delve into the process of mocking dependencies in a DI container when using WebApplicationFactory, and offer some insights ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found