Представь, что у тебя есть проект современного приложения, сделанный во времена релиза .NET Core 6. Само собой, его структура немного отличается от старых версий .NET (где было 2 отдельных файла — Startup.cs и Program.cs)
Давай разберём различия между старой и новой структурой — это пригодится для дальнейших объяснений
Структура проекта времён .NET Core 5
Startup.cs
Здесь мы обычно регистрировали все сервисы, конфиги и классы.
По сути, это стартовая точка приложения. Здесь, например, я добавил несколько строк кода для создания scope для Entity Context и запуска первоначальных миграций базы данных.
Оба старых файла — Program.cs и Startup.cs — теперь объединены в один файл Program.cs, и внутри больше нет никаких классов. Только чистые функции для добавления новых модификаций.
Типичный код Program.cs для проекта .NET Core 6+
var builder = WebApplication.CreateBuilder(args);//...builder.Services.AddControllers();// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbucklebuilder.Services.AddEndpointsApiExplorer();builder.Services.AddSwaggerGen();var app = builder.Build();//...if(app.Environment.IsDevelopment()){ app.UseSwagger(); app.UseSwaggerUI();}app.UseAuthorization();
Структура .NET Core 5 vs 6 — плюсы и минусы (+ решение проблем)
Плюсы
1 простой файл вместо 2
меньше обёрток классов — код проще и чище
появился новый webApplicationBuilder
Минусы
У нас больше нет классов в program для построения связей. Например, для подключения таких библиотек, как Mediator или FluentValidation, нужно получать тип сборки по имени, пример:
Решение проблемы с именем корневой сборки в .NET Core 6
Один из возможных вариантов решения — добавить эту строку в конец файла Program.csz:
// Make the implicit Program class public so test projects can access itpublicpartialclassProgram{}
Теперь можно использовать конструкции вроде typeof(Program) или WebApplicationFactory<Program> (при написании тестов)
Настройка тестового сервера в .NET Core 5
Здесь у нас есть nuget-пакет Microsoft.TestPlatform.TestHost вместе с Microsoft.AspNetCore.TestHost.
Вот TestServerFixture из одного из моих проектов, который связан с Program из реального приложения:
publicclassTestServerFixture:IDisposable{privatereadonlyTestServer _testServer;publicHttpClient Client {get;}publicTestServerFixture(){var builder =newWebHostBuilder()// .UseContentRoot(GetContentRootPath()).UseEnvironment("Development").UseConfiguration(FakeConfiguration.GetInstance()).UseStartup<Startup>();// Uses Start up class from your API Host project to configure the test server _testServer =newTestServer(builder); Client = _testServer.CreateClient();}// ...}
Юнит-тесты для контроллеров и утилит — хороший метод, но я также предпочитаю иметь реально запущенный экземпляр приложения для своих тестов, с возможностью отправлять настоящие POST- и GET-запросы.
Поэтому многие в интернете начинают строить отдельную конфигурацию для запуска такого тестового виртуального узла, но на самом деле у нас уже есть все необходимые настройки в файле Program.cs. Давай его и используем! Но нужно внести в него некоторые изменения, например — использовать не настоящую физическую базу данных, а базу в памяти.
Прежде всего, теперь мы можем ссылаться на класс Program.cs и использовать его в сочетании с классом WebApplicationFactory: