-
Notifications
You must be signed in to change notification settings - Fork 748
/
AutofacPlugin.cs
98 lines (90 loc) · 4.72 KB
/
AutofacPlugin.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using System;
using Autofac;
using SpecFlow.Autofac;
using TechTalk.SpecFlow;
using TechTalk.SpecFlow.Infrastructure;
using TechTalk.SpecFlow.Plugins;
using TechTalk.SpecFlow.UnitTestProvider;
[assembly: RuntimePlugin(typeof(AutofacPlugin))]
namespace SpecFlow.Autofac
{
using BoDi;
using TechTalk.SpecFlow;
public class AutofacPlugin : IRuntimePlugin
{
private static Object _registrationLock = new Object();
public void Initialize(RuntimePluginEvents runtimePluginEvents, RuntimePluginParameters runtimePluginParameters, UnitTestProviderConfiguration unitTestProviderConfiguration)
{
runtimePluginEvents.CustomizeGlobalDependencies += (sender, args) =>
{
// temporary fix for CustomizeGlobalDependencies called multiple times
// see https://github.com/techtalk/SpecFlow/issues/948
if (!args.ObjectContainer.IsRegistered<IContainerBuilderFinder>())
{
// an extra lock to ensure that there are not two super fast threads re-registering the same stuff
lock (_registrationLock)
{
if (!args.ObjectContainer.IsRegistered<IContainerBuilderFinder>())
{
args.ObjectContainer.RegisterTypeAs<AutofacTestObjectResolver, ITestObjectResolver>();
args.ObjectContainer.RegisterTypeAs<ContainerBuilderFinder, IContainerBuilderFinder>();
}
}
// workaround for parallel execution issue - this should be rather a feature in BoDi?
args.ObjectContainer.Resolve<IContainerBuilderFinder>();
}
};
runtimePluginEvents.CustomizeScenarioDependencies += (sender, args) =>
{
args.ObjectContainer.RegisterFactoryAs<IComponentContext>(() =>
{
var containerBuilderFinder = args.ObjectContainer.Resolve<IContainerBuilderFinder>();
var createScenarioContainerBuilder = containerBuilderFinder.GetCreateScenarioContainerBuilder();
var containerBuilder = createScenarioContainerBuilder();
RegisterSpecflowDependecies(args.ObjectContainer, containerBuilder);
var container = containerBuilder.Build();
return container.BeginLifetimeScope();
});
};
}
/// <summary>
/// Fix for https://github.com/gasparnagy/SpecFlow.Autofac/issues/11 Cannot resolve ScenarioInfo
/// Extracted from
/// https://github.com/techtalk/SpecFlow/blob/master/TechTalk.SpecFlow/Infrastructure/ITestObjectResolver.cs
/// The test objects might be dependent on particular SpecFlow infrastructure, therefore the implemented
/// resolution logic should support resolving the following objects (from the provided SpecFlow container):
/// <see cref="ScenarioContext" />, <see cref="FeatureContext" />, <see cref="TestThreadContext" /> and
/// <see cref="IObjectContainer" /> (to be able to resolve any other SpecFlow infrastucture). So basically
/// the resolution of these classes has to be forwarded to the original container.
/// </summary>
/// <param name="objectContainer">SpecFlow DI container.</param>
/// <param name="containerBuilder">Autofac ContainerBuilder.</param>
private void RegisterSpecflowDependecies(
IObjectContainer objectContainer,
global::Autofac.ContainerBuilder containerBuilder)
{
containerBuilder.Register(ctx => objectContainer).As<IObjectContainer>();
containerBuilder.Register(
ctx =>
{
var specflowContainer = ctx.Resolve<IObjectContainer>();
var scenarioContext = specflowContainer.Resolve<ScenarioContext>();
return scenarioContext;
}).As<ScenarioContext>();
containerBuilder.Register(
ctx =>
{
var specflowContainer = ctx.Resolve<IObjectContainer>();
var scenarioContext = specflowContainer.Resolve<FeatureContext>();
return scenarioContext;
}).As<FeatureContext>();
containerBuilder.Register(
ctx =>
{
var specflowContainer = ctx.Resolve<IObjectContainer>();
var scenarioContext = specflowContainer.Resolve<TestThreadContext>();
return scenarioContext;
}).As<TestThreadContext>();
}
}
}