Как внедрить CustomWebApplicationFactory в ASP.NET Основные Интеграционные тесты 3.1?

#c# #asp.net-core #integration-testing

Вопрос:

Я использую Microsoft ASP.NET Основная статья по тестированию интеграции и Moq.Contrib.Пример проекта HttpClient .NET 5 для настройки проекта IntegrationTest. Мое настоящее приложение и тестовый проект-.NET Core 3.1. Я получаю ошибку в конструкторе: Ошибка

Не знаю, в чем тут проблема. Вот тестовый класс:

 using FluentAssertions;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Moq.Contrib.HttpClient;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;

namespace API.IntegrationTests
{
    // This shows how you can mock HttpClient at the service collection level in integration tests. Note: "factory" and
    // "client" here are part of the integration test framework, TestServer, not our mock. For more info on integration
    // tests in ASP.NET Core, see https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests
    public class ExampleTests : IClassFixture<CustomWebApplicationFactory<Startup>>
    {
        private readonly CustomWebApplicationFactory<Startup> factory;
        private readonly Mock<HttpMessageHandler> githubHandler = new Mock<HttpMessageHandler>();

        public ExampleTests(CustomWebApplicationFactory<Startup> factory)
        {
            this.factory = factory.WithWebHostBuilder(builder =>
            {
                builder.ConfigureTestServices(services =>
                {
                    // This will configure the "github" named client to use our mock handler while keeping the default
                    // IHttpClientFactory infrastructure and any configurations made in Startup intact (as opposed to
                    // replacing the IHttpClientFactory implementation outright). This will work with typed clients,
                    // too. For the default (unnamed) client, use `Options.DefaultName`.
                    services.AddHttpClient("github")
                        .ConfigurePrimaryHttpMessageHandler(() => githubHandler.Object);
                });
            });
        }

        [Fact]
        public async Task GetReposTest()
        {
            // This is the integration test client used to make requests against the ASP.NET Core app under test
            var client = factory.CreateClient();

            var mockRepos = new GitHubRepository[]
            {
                new GitHubRepository()
                {
                    Name = "Foo",
                    Language = "TypeScript",
                    Stars = 39
                },
                new GitHubRepository()
                {
                    Name = "Bar",
                    Language = "C#",
                    Stars = 9001 // It's over 9000!!!
                }
            };

            var expectedResponse =
                "Foo (TypeScript, ★39)n"  
                "Bar (C#, ★9001)n";

            // Notice there was no need to set a BaseAddress in this test class. All of the dependency injection and the
            // AddHttpClient() in ConfigureServices() are essentially unchanged and working as they would normally.
            githubHandler.SetupRequest(HttpMethod.Get, "https://api.github.com/users/maxkagamine/repos")
                .ReturnsResponse(JsonConvert.SerializeObject(mockRepos), "application/vnd.github.v3 json");

            var response = await client.GetStringAsync("/");

            response.Should().Be(expectedResponse,
                "the app's requests should hit the mock handler now instead of the real API");
        }
    }
}
 

А вот и CustomWebApplicationFactory :

 using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Linq;

namespace API.IntegrationTests
{
    public class CustomWebApplicationFactory<TStartup>
    : WebApplicationFactory<TStartup> where TStartup : class
    {
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            builder.ConfigureServices(services =>
            {
                var descriptor = services.SingleOrDefault(
                    d => d.ServiceType ==
                        typeof(DbContextOptions<ApplicationDBContext>));

                services.Remove(descriptor);

                //services.AddDbContext<ApplicationDBContext>(options =>
                //{
                //    options.UseInMemoryDatabase("InMemoryDbForTesting");
                //});

                var sp = services.BuildServiceProvider();

                using (var scope = sp.CreateScope())
                {
                    var scopedServices = scope.ServiceProvider;
                    var db = scopedServices.GetRequiredService<ApplicationDBContext>();
                    var logger = scopedServices
                        .GetRequiredService<ILogger<CustomWebApplicationFactory<TStartup>>>();

                    db.Database.EnsureCreated();

                    //try
                    //{
                    //    Utilities.InitializeDbForTests(db);
                    //}
                    //catch (Exception ex)
                    //{
                    //    logger.LogError(ex, "An error occurred seeding the "  
                    //        "database with test messages. Error: {Message}", ex.Message);
                    //}
                }
            });
        }
    }
}