gasparnagy / specflow.autofac Goto Github PK
View Code? Open in Web Editor NEWSpecFlow plugin for using Autofac as a dependency injection framework for step definitions
License: Apache License 2.0
SpecFlow plugin for using Autofac as a dependency injection framework for step definitions
License: Apache License 2.0
When you have a test using FeatureContext on the BeforeFeature constructor like:
[BeforeFeature]
public static void BeforeFeature(FeatureContext feature)
{
//Testing Autofac plugin
}
The SpecFlow.Autofac plugin will try to resolve the AutofacTestObjectResolver class BEFORE registering the CustomizeScenarioDependencies and throw an error:
Message: OneTimeSetUp: BoDi.ObjectContainerException : Interface cannot be resolved: Autofac.IComponentContext
Is there a fix for it?
I am trying to run tests in parallel using the NUnit Parallelizable attribute (http://www.specflow.org/documentation/Parallel-Execution/). When my tests run serially they all work fine. Running them in parallel causes the following error on some tests:
System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
----> System.ArgumentException : An item with the same key has already been added.
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Delegate.DynamicInvokeImpl(Object[] args)
at BoDi.ObjectContainer.InvokeFactoryDelegate(Delegate factoryDelegate, ResolutionList resolutionPath, RegistrationKey keyToResolve)
at BoDi.ObjectContainer.FactoryRegistration.Resolve(ObjectContainer container, RegistrationKey keyToResolve, ResolutionList resolutionPath)
at BoDi.ObjectContainer.ResolveObject(RegistrationKey keyToResolve, ResolutionList resolutionPath)
at BoDi.ObjectContainer.Resolve(Type typeToResolve, ResolutionList resolutionPath, String name)
at BoDi.ObjectContainer.Resolve[T](String name)
at SpecFlow.Autofac.AutofacBindingInstanceResolver.ResolveBindingInstance(Type bindingType, IObjectContainer scenarioContainer)
at lambda_method(Closure , IContextManager )
at TechTalk.SpecFlow.Bindings.BindingInvoker.InvokeBinding(IBinding binding, IContextManager contextManager, Object[] arguments, ITestTracer testTracer, TimeSpan& duration)
at TechTalk.SpecFlow.Infrastructure.TestExecutionEngine.FireEvents(HookType bindingEvent)
at TechTalk.SpecFlow.Infrastructure.TestExecutionEngine.OnScenarioStart(ScenarioInfo scenarioInfo)
at Dyson.Jda.AutomatedTesting.Features.AwardEntrantSignInFeature.ScenarioSetup(ScenarioInfo scenarioInfo)
at Dyson.Jda.AutomatedTesting.Features.AwardEntrantSignInFeature.AwardEntrantCannotSignInWithInvalidCredentials(String email, String password, String[] exampleTags) in C:\Code\Git\james-dyson-award\JDA\AutomatedTests\Dyson.Jda.AutomatedTesting\Features\AwardEntrantSignIn.feature:line 32
--ArgumentException
at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at BoDi.ObjectContainer.TypeRegistration.Resolve(ObjectContainer container, RegistrationKey keyToResolve, ResolutionList resolutionPath)
at BoDi.ObjectContainer.ResolveObject(RegistrationKey keyToResolve, ResolutionList resolutionPath)
at BoDi.ObjectContainer.Resolve(Type typeToResolve, ResolutionList resolutionPath, String name)
at BoDi.ObjectContainer.Resolve[T](String name)
at SpecFlow.Autofac.AutofacPlugin.<>c__DisplayClass0_0.<Initialize>b__2()
BoDi by itself supports running tests in parallel and I have done this successfully on another project. Is it supported by this plugin?
Hi,
I have a step class where I would like to inject the current ScenarioInfo instance in order to retrieve the test tile. The problem is that if I add ScenarioInfo as a constructor parameter, the test fails with:
Test method MyCalculator.Specs.Features.AdditionFeature.AddTwoNumbers threw exception:
Autofac.Core.DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MyCalculator.Specs.StepDefinitions.CalculatorSteps' can be invoked with the available services and parameters:
Cannot resolve parameter 'TechTalk.SpecFlow.ScenarioInfo scenarioInfo' of constructor 'Void .ctor(MyCalculator.ICalculator, TechTalk.SpecFlow.ScenarioInfo)'.
How can I use ScenarioInfo, without using the static ScenarioContext.Current?
Thanks
#Request
@gasparnagy
My project heavily dependent on Specflow.Autofac plugin. Are you planning to update this plugin for latest Specflow V3 ?
Hi,
I am trying to enable running tests in parallel, but I cannot seem to make it work.
I had an AfterScenario hook which initially was verifying the static ScenarioContext.Current.TestError value.
All the DI registration is made using Specflow.Autofac package.
After upgrading NUnit to version 3.6.1, it threw an exception complaining about the use of this static ScenarioContext with a link to http://specflow.org/documentation/Parallel-Execution/
I made the update in my step class as in above link:
`
[Binding]
public class StepsWithScenarioContext
{
private readonly ScenarioContext scenarioContext;
public StepsWithScenarioContext(ScenarioContext scenarioContext)
{
if (scenarioContext == null) throw new ArgumentNullException("scenarioContext");
this.scenarioContext = scenarioContext;
}
[AfterScenario]
public void AfterScenario()
{
if (_scenarioContext.TestError != null)
//do something
}
}
`
But now, the below exception is thrown:
Cannot resolve parameter 'TechTalk.SpecFlow.ScenarioContext scenarioContext'
I tried to find a way to register this scenario context into my DI, but wasn't able to find a way.
Did anyone else had this issue?
Is there a way to register the ScenarioContext into Specflow.Autofac registration?
Thank you and happy coding!
<specFlow>
<plugins>
<add name="SpecFlow.Autofac" type="Runtime" />
</plugins>
<stepAssemblies>
<stepAssembly assembly="StepDefinitions" />
</stepAssemblies>
</specFlow>
Expected Result: Test runs successfully.
Actual result : Exception has been thrown by the target of an invocation.
----> System.Exception : Unable to find scenario dependencies! Mark a static method that returns a ContainerBuilder with [ScenarioDependencies]! => I already have it defined under support directory in my tests project.
Note! If I remove the step assembly dependency from App.config, the test starts, but fails with "No matching step definition found for the step. Use the following code to create one"
In a custom DI solution using Autofac, with [ScenarioDependencies]
as "entry point" for Autofac container builder, it'd be a very useful feature to have access to built IContainer
in order to easily and manually resolve dependencies where needed.
Currently, we're forced to use a constructor injection, which is a limitation in some use cases.
This would also solve the issue some users had with the multitenant setting, as it requires access to built IContainer
.
@gasparnagy thank you for your hard work and let me know your thoughts. It's a simple requirement, which can be easily deployed on the official NuGet package and I'd rather use the official one than build my own.
ScenarioContext.Current.Pending()
).<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="SpecFlow" Version="3.0.188" />
<PackageReference Include="SpecFlow.Autofac" Version="1.2.0" />
<PackageReference Include="SpecFlow.Tools.MsBuild.Generation" Version="3.0.188" />
<PackageReference Include="SpecFlow.xUnit" Version="3.0.188" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
</ItemGroup>
using Autofac;
using SpecFlow.Autofac;
using TechTalk.SpecFlow;
[Binding]
class SpecDependancies
{
[ScenarioDependencies]
public static ContainerBuilder CreateContainerBuilder()
{
return new ContainerBuilder();
}
}
I have an error on [ScenarioDependencies]
and on using Specflow.Autofac;
telling me that
The type or namespace name could not be found
.
If I open the NuGet tree in Visual Studio, under the Specflow.Autofac, the SpecFlow.Autofac.SpecFlowPlugin.dll
isn't there. Which is different if I check under the SpecFlow.xUnit package since the TechTalk.SpecFlow.xUnit.SpecFlow.dll
appears and it also is copied in the output folder.
I looked around the Specflow plugin documentation and the NuGet samples seems quite different from the plugin, I can't say if this could be a breaking change with v3... I'm still new in creating NuGet packages.
It works fine though, if I add a strict reference to the SpecFlow.Autofac.SpecFlowPlugin.dll
, so the plugin should be good, but NuGet helps a lot in managing external dependencies.
#5 is related to this. This plugin totally fails to provide proper lifetime and scope semantics. For every test a new container is created. This will be horribly inefficient for any complex system of component registrations (and may actually cause problems in some cases?). The container should be created only once, and a new lifetime scope should be created for each scenario (and should be properly disposed after the scenario). Honestly, I don't know if this is even possible with the existing plugin architecture? Between this and the lack of support for ScenarioContext and ScenarioInfo I'm not sure if I can even use this plugin.
Hi,
We successfully added Specflow.Autofac to our project, but quite a few times we felt the need of an [FeatureDependencies] attribute to inject some dependencies at the feature level instead of scenario.
I'm not sure about the impact and how complex this change would be, but I would definitely want to see if someone else had the same issue.
Thank you and happy coding!
We have issues using SpecFlow 2.1 which have been resovled in SpecFlow 2.2. PLEASE can you address this issue... System.Typeload Exception: Could not load type TechTalk.Specflow.Infrastructre.IBindingInstanceResolver from assembly TechTalk.Specflow Version 2.2.0.0
Hi,
I'm trying to apply multitenant DI of Autofac with Specflow.
As described in autofac multitenant doc page, general usage should be like that:
var builder = new ContainerBuilder();
builder.RegisterType<Consumer>().As<IDependencyConsumer>().InstancePerDependency();
builder.RegisterType<BaseDependency>().As<IDependency>().SingleInstance();
var appContainer = builder.Build();
var tenantIdentifier = new MyTenantIdentificationStrategy();
var mtc = new MultitenantContainer(tenantIdentifier, appContainer);
// Configure the overrides for each tenant by passing in the tenant ID
// and a lambda that takes a ContainerBuilder.
mtc.ConfigureTenant('1', b => b.RegisterType<Tenant1Dependency>().As<IDependency>().InstancePerDependency());
mtc.ConfigureTenant('2', b => b.RegisterType<Tenant2Dependency>().As<IDependency>().SingleInstance());
Specflow.Autofac is used by creating a static containerbuilder method with [ScenarioDependencies] attribute. This attribute requires unbuilt container to inject dependencies. However multitenant configuration requires built one. That's why I get the exception
"System.InvalidOperationException : Build() or Update() can only be called once on a ContainerBuilder."
when I try to use above multitenant code with [ScenarioDependencies] attribute.
Is there any work around solution for this problem? Or should I write my custom DI solution instead of [ScenarioDependencies] attribute?
Hi,
If I register types that implement IDisposable in the Autofac Container, these are not disposed after the scenario has run. This works if I use the BoDI container.
Thanks.
Hi
I wanted to ask if is there any plan to make it work with Specflow 2.2?
Right now, even using the pull request from @zaccharles (#7) I still face some issues when my BeforeFeature hook has FeatureContext as parameter to be resolved.
Basically it goes to ResolveBindingInstance before registering scenario/feature in runtimePluginEvents.CustomizeScenarioDependencies
That only happens if you are using 2.2 Specflowchanges (Like I mentioned, BeforeFeature with feature context as parameter)
Thanks!
Does Specflow.Autofac works with Specflow 2.2?
When I try to run tests I get:
OneTimeSetUp: System.TypeLoadException : Could not load type 'TechTalk.SpecFlow.Infrastructure.IBindingInstanceResolver' from assembly 'TechTalk.SpecFlow, Version=2.2.0.0, Culture=neutral, PublicKeyToken=0778194805d6db41'.
With Specflow 2.1 works fine. Is there a way to solve this?
Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.