Я пытаюсь настроить свои тесты Specflow (V. 3.0.155 beta) в .Net Core 2.1 Web API, и я придерживаюсь структуры, которую я использовал в некоторых предыдущих проектах .Net Framework Web API.Мы работали над этим.
Но у меня возникают проблемы, когда я пытаюсь разрешить свои зависимости, кажется, что я выхожу из области видимости, поэтому, когда я пытаюсь разрешить что-то, то есть мой тестВ контексте данных я получаю следующую ошибку от SpecFlow:
Сообщение: SimpleInjector.ActivationException: зарегистрированный делегат для типа ProjectNexusContext выдал исключение.ProjectNexusContext зарегистрирован как стиль жизни «Async Scoped», но экземпляр запрашивается вне контекста активной области (Async Scoped).----> SimpleInjector.ActivationException: ProjectNexusContext зарегистрирован как образ жизни с асинхронной областью, но экземпляр запрашивается вне контекста активной области (асинхронной области).
Трассировка стека:
Результат StackTrace: в SimpleInjector.InstanceProducer.GetInstance ()
в SimpleInjector.Container.GetInstanceTService в ProjectNexus.ApplicationContext.ResolveT в C: \ Users \ dawes \ source \ repos \ Projectexexus ProjectApplicationContext.cs: строка 18 в ProjectNexus.Engine.Specs.LifecycleTestHooks.AfterStep () в C: \ Users \ dawes \ source \ repos \ ProjectNexus \ ProjectNexus.Engine.Specs \ LifecycleTestHooks.cs: строка 37 в TechTalk.SpecFlow.Bindings.BindingInvoker.InvokeBinding (IBinding привязка, IContextManager contextManager, аргументы Object [], ITestTracer testTracer, TimeSpan & duration) в D: \ a \ 1 \ s \ TechTalk.SpecFlow \ Bindings \ BindingInvoker.cs: строка 73 в TechTalk.SpecFlow.Infrastructure.TestExecutionEngine.InvokeHook (IBindingInvoker invoker, IHookBinding hookBinding, HookType hookType) в D: \ a \ 1 \ s \ TechTalk.SpecFlow \ Infrastructure \ TestExecutionEngine.cs: строка 246 в TechTalk.SpecFlow.Infrastructure.TestExecutionEngine.FireEvents (HookType hookType) в D: \ as \ TechTalk.SpecFlow \ Infrastructure \ TestExecutionEngine.cs: строка 232 в TechTalk.SpecFlow.Infrastructure.TestExecutionEngine.ExecuteStep (IContextManager contextManager, stepInstance stepInstance) в D: \ a \ 1 \ s \ TechTalkstructure.Sec. Test.SecF: строка 367 в TechTalk.SpecFlow.Infrastructure.TestExecutionEngine.Step (StepDefinitionKeyword stepDefinitionKeyword, строковое ключевое слово, текст строки, строковый multilineTextArg, таблица tableArg) в D: \ a \ 1 \ s \ TechTalk.SpecFlow \ Infrastructure \.475 в TechTalk.SpecFlow.TestRunner.Given (текст строки, строковый multilineTextArg, таблица tableArg, ключевое слово String) в D: \ a \ 1 \ s \ TechTalk.SpecFlow \ TestRunner.cs: строка 75 в ProjectNexus.Engine.Specs.Tests.Client.Authentication.LogInFeature.FeatureBackground () в C: \ Users \ dawes \source \ repos \ ProjectNexus \ ProjectNexus.Engine.Specs \ Tests \ Client \ Authentication \ Log In.feature: строка 7 в ProjectNexus.Engine.Specs.Tests.Client.Authentication.LogInFeature.LogInWithAValidUsernameAndPassword () в C: Users \ Users\ source \ repos \ ProjectNexus \ ProjectNexus.Engine.Specs \ Tests \ Client \ Authentication \ Log In.feature: строка 6 - АктивацияException в SimpleInjector.Scope.GetScopelessInstance [TImplementation] (ScopedRegistration 1
registration) at
SimpleInjector.Advanced.Internal.LazyScopedRegistration
1.GetInstance (область действия области)at lambda_method (Closure) at SimpleInjector.InstanceProducer.GetInstance () Сообщение о результате: SimpleInjector.ActivationException: зарегистрированный делегат для типа ProjectNexusContext вызвал исключение.ProjectNexusContext зарегистрирован как стиль жизни «Async Scoped», но экземпляр запрашивается вне контекста активной области (Async Scoped).----> SimpleInjector.ActivationException: ProjectNexusContext зарегистрирован как образ жизни с асинхронной областью действия, но экземпляр запрашивается вне контекста активной области действия (асинхронной области действия).РезультатStandardOutput: данные Следующие пользователи хранятся в базе данных --- аргумент шага таблицы --- |Forneame |Фамилия |Имя пользователя|Джон |Смит |JS001 |-> ошибка: зарегистрированный делегат для типа ProjectNexusContext выдал исключение.ProjectNexusContext зарегистрирован как образ жизни «Async Scoped», но экземпляр запрашивается вне контекста активной области (Async Scoped).
Я использую Simple Injector 4.4.2 и в моем тестепроект, и я настраиваю свой контейнер и регистрирую свои экземпляры в методе статического класса, который вызывается в хуке жизненного цикла BeforeTestRun SpecFlow.
Затем в хуке BeforeScenario я начинаю новую область действия AsyncScopedLifestyle в указанном контейнере, котораябыть использованным повсюду для данного сценария.Далее, в моем хакере AfterScenario я избавляюсь от этого образа жизни.Я просмотрел документацию SimpleInjector, касающуюся этого образа жизни, и знаю, что это исключение выдается, когда он находится вне контекста активной области, но я не могу понять, почему я нахожусь вне активного контекста!
После проверки области действияв хуке BeforeStep я вижу, что свойство CurrentScope в ScopeManager, хотя и не удалено, имеет значение null, поэтому я явно вне контекста активной области.
Это никогда ранее не было проблемой, и кодточно так же, как в вышеупомянутых предыдущих проектах, которые используют SimpleInjector в своих тестовых проектах точно таким же образом.Я даже прошел их и проверил область видимости в крючке BeforeStep, а CurrentScope в ScopeManager был областью действия, поэтому они явно не выходят за пределы этой области.
Я надеялся, что кто-то может увидеть что-то, что я 'отсутствует или есть некоторые предложения относительно того, как решить эту проблему.
Я включил код для моих перехватчиков SpecFlow и настройки IoC ниже:
перехватчиков SpecFlow:
[Binding]
public class LifecycleTestHooks
{
[BeforeTestRun]
public static void BeforeTestRun()
{
TestIocConfiguration.Configure();
}
[BeforeScenario]
public void BeforeScenario()
{
TestIocConfiguration.StartExecutionScope();
}
[BeforeStep]
public void BeforeStep()
{
var projectDbContext = ApplicationContext.Resolve<ProjectNexusContext>();
projectDbContext.Database.BeginTransaction();
}
[AfterStep]
public void AfterStep()
{
var projectDbContext = ApplicationContext.Resolve<ProjectNexusContext>();
if (projectDbContext.Database.CurrentTransaction != null)
{
try
{
projectDbContext.Database.CommitTransaction();
}
catch (Exception)
{
projectDbContext.Database.RollbackTransaction();
throw;
}
}
TestIocConfiguration.CheckExecutionScope();
}
[AfterScenario]
public void AfterScenario()
{
TestIocConfiguration.EndExecutionScope();
}
}
Настройка IoC
public class TestIocConfiguration
{
static Container container;
public static void Configure()
{
container = ApplicationContext.Container;
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
EngineInitialisation.Initialise();
container.Options.AllowOverridingRegistrations = true;
RegisterTestDatabaseContext();
RegisterTestApplicationConfiguration();
RegisterTestLdapConnectionService();
RegisterTestContext();
}
private static void RegisterTestDatabaseContext()
{
var testContext =
new ProjectNexusContext(new TestContextHelper().GetDbContextOptionsBuilder());
testContext.Database.OpenConnection();
testContext.Database.EnsureCreated();
container.Register<ProjectNexusContext>(() => testContext, Lifestyle.Scoped);
}
private static void RegisterTestLdapConnectionService()
{
container.Register<ILdapConnectionService, TestLdapConnectionService>(Lifestyle.Scoped);
}
private static void RegisterTestApplicationConfiguration()
{
var appConfig = new ApplicationConfiguration
{
LdapHost = "",
LdapPort = 0,
ApplicationSecret = "TestSecret",
TokenExpirationDays = 1
};
container.Register<ApplicationConfiguration>(() => appConfig, Lifestyle.Scoped);
}
private static void RegisterTestContext()
{
container.Register<TestContext>(Lifestyle.Singleton);
}
public static Scope StartExecutionScope()
{
return AsyncScopedLifestyle.BeginScope(container);
}
public static void EndExecutionScope()
{
Lifestyle.Scoped.GetCurrentScope(container)?.Dispose();
}
}
Контекст приложения
public class ApplicationContext
{
public static readonly Container Container;
public static readonly Mapper Mapper;
static ApplicationContext()
{
Container = new Container();
}
public static T Resolve<T>() where T : class
{
return Container.GetInstance<T>();
}
public static Cast Resolve<T, Cast>()
where Cast : T
where T : class
{
return (Cast)Container.GetInstance<T>();
}
}