'Typed HTTP client and CustomWebApplicationFactory

We are using .NET Core 3.1 to develop a REST API service. We would like to implement integration tests. We found this article which explains how to use WebApplicationFactory.

CustomWebApplicationFactory.cs

public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureAppConfiguration((context, conf) =>
        {
            var p = Path.Combine(Directory.GetCurrentDirectory(), "appsettings.test.json");
            conf.AddJsonFile(p);
        });

        builder.ConfigureServices(services =>
        {
            var configuration = services.BuildServiceProvider().GetRequiredService<IConfiguration>();
            services.AddSingleton<RestApiConfigurationClient>(configuration.GetSection("RestApi").Get<RestApiConfigurationClient>());
            services.AddHttpClient<RestApiHttpClient>();
        });
    }
}

RestApiTestBase.cs

public class RestApiTestBase
{
    private readonly RestApiHttpClient _restApiHttpClient;

    protected RestApiTestBase(CustomWebApplicationFactory<Rest.Server.Startup> factory)
    {
        var scope = factory.Services.CreateScope();
        _restApiHttpClient = scope.ServiceProvider.GetRequiredService<RestApiHttpClient>();
    }
}

[CollectionDefinition("RestApi_test_collection")]
public class RestApiTestCollection : ICollectionFixture<CustomWebApplicationFactory<Rest.Server.Startup>>
{

}

RestApiHttpClient.cs

public class RestApiHttpClient : IProductsService
{
    private readonly HttpClient _httpClient;
    private readonly IProductsService _productsService;

    public RestApiHttpClient(HttpClient httpClient, RestApiConfigurationClient configuration)
    {
        if (configuration == null)
        {
            throw new Exception("Configuration is not provided");
        }

        httpClient.BaseAddress = new Uri(configuration.URL);
        httpClient.SetAuthorizationHeader(configuration.Username, configuration.Password);
        httpClient.Timeout = TimeSpan.FromMilliseconds(configuration.TimeoutMs);

        _httpClient = httpClient;

        _productsService = new ProductsService(this);
    }

    public HttpClient GetHttpClient()
    {
        return _httpClient;
    }

    public async Task<GetProductByIdResponse> GetProductById(int id)
    {
        return await _productsService.GetProductById(id);
    }
}

ProductsService.cs

public class ProductsService : IProductsService
{
    private readonly HttpClient _httpClient;

    public ProductsService(RestApiHttpClient httpClient)
    {
        _httpClient = httpClient.GetHttpClient();
    }

    public async Task<GetProductByIdResponse> GetProductById(int id)
    {
        var response = await _httpClient.GetAsync($"Products/{id}");
        return JsonConvert.DeserializeObject<GetProductByIdResponse>(await response.Content.ReadAsStringAsync());
    }
}

How can we inject HttpClient which can be created by WebApplicationFactory<TEntryPoint>.CreateClient() into typed HTTP client RestApiHttpClient?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source