Autofac¶
Introduction¶
SpecFlow plugin for using Autofac as a dependency injection framework for step definitions.
Currently supports
Autofac v4.0.0 or above
Step by step walkthrough of using SpecFlow.Autofac¶
1. Install plugin from NuGet into your SpecFlow project.¶
PM> Install-Package SpecFlow.Autofac
2. Create static methods somewhere in the SpecFlow project¶
Plugin supports both registration of dependencies globally and per scenario:
2.2 Configure dependencies to be resolved each time for a scenario:¶
Create a static method somewhere in the SpecFlow project to register scenario dependencies:
(Recommended to put it into the Support
folder) that returns void
and has one parameter of Autofac ContainerBuilder
, tag it with the [ScenarioDependencies]
attribute.
2.3 Configure your dependencies for the scenario execution within either the two methods [GlobalDependencies]
and [ScenarioDependencies]
or the single [ScenarioDependencies]
method.¶
2.4 You also have to register the step definition classes in the [ScenarioDependencies]
method, that you can do by either registering all public types from the SpecFlow project:¶
builder.RegisterAssemblyTypes(typeof(YourClassInTheSpecFlowProject).Assembly).SingleInstance();
2.5 or by registering all classes marked with the [Binding]
attribute:¶
You may use a provided extension method to do this, but importing:
using SpecFlow.Autofac.SpecFlowPlugin;
Then
containerBuilder.AddSpecFlowBindings(typeof(YourClassInTheSpecFlowProject))
Or overload
containerBuilder.AddSpecFlowBindings<YourClassInTheSpecFlowProject>()
Or manually register like so:
builder
.RegisterAssemblyTypes(typeof(TestDependencies).Assembly)
.Where(t => Attribute.IsDefined(t, typeof(BindingAttribute)))
.SingleInstance();
3. A typical dependency builder method for [GlobalDependencies]
with [ScenarioDependencies]
probably looks like this:¶
[GlobalDependencies]
public static void CreateGlobalContainer(ContainerBuilder containerBuilder)
{
// Register globally scoped runtime dependencies
Dependencies.RegisterGlobalDependencies(containerBuilder);
//TODO: add Services that are shared globally.
}
[ScenarioDependencies]
public static void CreateContainerBuilder(ContainerBuilder containerBuilder)
{
// Register scenario scoped runtime dependencies
Dependencies.RegisterScenarioDependencies(containerBuilder);
//TODO: add customizations, stubs required for testing
containerBuilder.AddSpecFlowBindings<TestDependencies>()
}
4. It is also possible to continue to use the legacy method as well, however this method is not compatible with global dependency registration and can only be used on it’s own like so:¶
Create a static method somewhere in the SpecFlow project to register scenario dependencies:
(Recommended to put it into the Support
folder) that returns an Autofac ContainerBuilder
and tag it with the [ScenarioDependencies]
attribute.
5. If you have an existing container, built and owned by your application under test, you can use that instead of letting SpecFlow manage your container¶
Create a static method in your SpecFlow project to return a lifetime scope from your container. Note that SpecFlow creates a second scope under yours,
so be sure to pair this use-case with the CreateContainerBuilder
method above to add your step bindings.
[FeatureDependencies]
public static ILifetimeScope GetFeatureLifetimeScope()
{
// TODO: Add any top-level dependencies here, though note that usually step bindings
// should be declared in the Configure method below, as this will ensure they
// are in the correct scope to inject ScenarioContext etc.
return containerScope.BeginLifetimeScope();
}
[ScenarioDependencies]
public static void ConfigureContainerBuilder(ContainerBuilder containerBuilder)
{
//TODO: add customizations, stubs required for testing
containerBuilder.AddSpecFlowBindings<TestDependencies>();
}