Язык программирования C#9 и платформа .NET5
Часть 454 из 642 Информация о книге
new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json", true, true).Build();public static ApplicationDbContext GetContext(IConfiguration configuration){var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();var connectionString = configuration.GetConnectionString("AutoLot");optionsBuilder.UseSqlServer(connectionString,sqlOptions => sqlOptions.<b>EnableRetryOn</b><b>Failure()</b>);return new ApplicationDbContext(optionsBuilder.Options);}Как вероятно вы помните, выделенный полужирным вызов
выбирает стратегию повтора SQL Server, которая будет автоматически повторять операции, потерпевших неудачу из-за кратковременных ошибок.EnableRetryOnFailure()Добавьте еще один статический метод, который будет создавать новый экземпляр
с применением того же самого подключения и транзакции, что и в переданном исходном контексте. Этот метод демонстрирует способ создания экземпляраApplicationDbContextиз существующего экземпляра с целью совместного использования подключения и транзакции:ApplicationDbContextpublic static ApplicationDbContext GetSecondContext(ApplicationDbContext oldContext,IDbContextTransaction trans){var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();optionsBuilder.UseSqlServer(oldContext.Database.GetDbConnection(),sqlServerOptions => sqlServerOptions.EnableRetryOnFailure());var context = new ApplicationDbContext(optionsBuilder.Options);context.Database.UseTransaction(trans.GetDbTransaction());return context;}Добавление класса BaseTest
Создайте в проекте новый каталог по имени
и добавьте туда новый файл классаBase. Модифицируйте операторыBaseTest.csследующим образом:usingusing System;using System.Data;using AutoLot.Dal.EfStructures;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Storage;using Microsoft.Extensions.Configuration;Сделайте класс абстрактным и реализующим
. Добавьте два защищенных свойстваIDisposableдля хранения экземпляров реализацииreadonlyиклассаIConfigurationи освободите экземплярApplicationDbContextв виртуальном методеApplicationDbContext:Dispose()namespace AutoLot.Dal.Tests.Base{public abstract class BaseTest : IDisposable{protected readonly IConfiguration Configuration;protected readonly ApplicationDbContext Context;public virtual void Dispose(){Context.Dispose();}}}Инфраструктура тестирования xUnit предоставляет механизм для запуска кода до и после прогона каждого теста. Классы тестов (называемые оснастками), которые реализуют интерфейс
, перед прогоном каждого теста будут выполнять код в конструкторе класса (в конструкторе базового класса и конструкторе производного класса в этом случае), называемый настройкой теста, а после прогона каждого теста — код в методеIDisposable(в производном и в базовом классах), называемый освобождением теста.Dispose()Добавьте защищенный конструктор, который создает экземпляр реализации
и присваивает его защищенной переменной класса. С применением конфигурации создайте экземплярIConfiguration, используя классApplicationDbContext, и присвойте его защищенной переменной класса:TestHelpersprotected BaseTest(){Configuration = TestHelpers.GetConfiguration();Context = TestHelpers.GetContext(Configuration);}Добавление вспомогательных методов для выполнения тестов в транзакциях
Последние два метода в классе
позволяют выполнять тестовые методы в транзакциях. Методы будут принимать в единственном параметре делегатBaseTest, создавать явную транзакцию (или вовлекать существующую транзакцию), выполнять делегатActionи затем проводить откат транзакции. Так делается для того, чтобы любые тесты создания/обновления/удаления оставляли базу данных в состоянии, в котором она пребывала до прогона теста. Поскольку классActionсконфигурирован с целью включения повторений при возникновении кратковременных ошибок, весь процесс обязан выполняться в соответствии со стратегией выполненияApplicationDbContext.ApplicationDbContextМетод
выполняется с применением одиночного экземпляраExecutelnATransaction(). МетодApplicationDbContextпозволяет нескольким экземплярамExecutelnASharedTransaction()совместно использовать транзакцию. Вы узнаете больше об упомянутых методах позже в главе, а пока добавьте в свой классApplicationDbContextследующий код:BaseTest