Переместить тестовый класс запуска ASP.NET за пределы корневого каталога проекта? - PullRequest
0 голосов
/ 04 июля 2019

У меня есть приложение Blazor (ASP.NET Core 3.0) (шаблон по умолчанию), и я хочу написать несколько интеграционных тестов с использованием Selenium. Для этого мне нужно запустить веб-приложение до запуска тестов.

Я делаю это, запустив

CreateHostBuilderWithStartup<Startup>(new string[0]).UseContentRoot(contentRoot).Build().RunAsync();

private static IHostBuilder CreateHostBuilderWithStartup<TStartup>(string[] args) where TStartup : class
    {
        return Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<TStartup>();
            });
    }

где contentRoot - путь к тестируемому проекту. Это работает нормально, сервер работает как положено.

Мое решение содержит 2 проекта - код приложения и тестовый код.

Однако, если я пытаюсь использовать класс Startup из тестового проекта, который наследуется от запуска (т.е. CreateHostBuilderWithStartup<TestStartup>), то сервер возвращает 500 внутренних ошибок сервера для каждого запроса. Ошибка в выводе консоли для сервера:

Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware: Error: An unhandled exception has occurred while executing the request.

System.InvalidOperationException: Cannot find the fallback endpoint specified by route values: { page: /_Host, area:  }.
   at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.DynamicPageEndpointMatcherPolicy.ApplyAsync(HttpContext httpContext, CandidateSet candidates)
   at Microsoft.AspNetCore.Routing.Matching.DfaMatcher.SelectEndpointWithPoliciesAsync(HttpContext httpContext, IEndpointSelectorPolicy[] policies, CandidateSet candidateSet)
   at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.<Invoke>g__AwaitMatch|6_1(EndpointRoutingMiddleware middleware, HttpContext httpContext, Task matchTask)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
'dotnet.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App\3.0.0-preview6.19307.2\Microsoft.AspNetCore.Http.Extensions.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.

Если я перенесу TestStartup в основной проект кода, это будет работать нормально, но в идеале я хочу сохранить тестовый код в тестовом проекте. Мне нужно использовать этот класс TestStartup, чтобы я мог переопределить метод ConfigureServices, чтобы изменить внедренные зависимости.

Итак, суть этого вопроса в том, могу ли я иметь класс Startup вне корневого каталога проекта ASP.NET Core, который я запускаю?

Любая помощь с этим будет высоко ценится!

1 Ответ

0 голосов
/ 23 июля 2019

Из многих экспериментов и исследований кажется, что в настоящее время невозможно переместить класс Startup из-за ошибки, связанной с несоответствием пути ContentRoot, установленному с помощью метода UseContentRoot. Эта ошибка отслеживается проблемой # 11921 в AspNetCore GitHub.

Очень хакерский обходной путь, если вам нужно иметь возможность вставлять зависимости из тестового проекта, - это создать статический класс Dependencies в вашем главном проекте со статическим полем Action<IStartupConfiguration> RegisterDependencies, которое затем вызывается при запуске. класс:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddServerSideBlazor();
    Dependencies.RegisterDependencies(services);
}

Затем в Program.cs установите RegisterDepenedencies для регистрации необходимых вам зависимостей:

public static void Main(string[] args)
{
    Dependencies.RegisterDependencies = s =>
    {
        s.AddSingleton<IWeatherForecastService, WeatherForecastService>();
    };

    CreateHostBuilder(args).Build().Run();
}

Теперь вы можете изменить этот метод в тестовом проекте, чтобы настроить различные зависимости при запуске интеграционных тестов. В вашем тестовом проекте:

Dependencies.RegisterDependencies = s =>
{
    s.AddSingleton<IWeatherForecastService, MockWeatherForecastService>();
};

Это очень странно, надеюсь, проблема ContentRoot исправлена, вместо нее следует использовать замену корня контента на основной проект

...