Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specflow Hooks IObjectContainer null #2

Open
danny-bos-developer opened this issue May 4, 2018 · 5 comments
Open

Specflow Hooks IObjectContainer null #2

danny-bos-developer opened this issue May 4, 2018 · 5 comments

Comments

@danny-bos-developer
Copy link

Hi, I'm using this specflow plugin because we have castle in all out projects. I only have one problem, specflow has some hooks where you can execute code:
[BeforeFeature()]
public static void BeforeFeature(IObjectContainer objectContainer) { }

[AfterFeature()]
public static void AfterFeature(IObjectContainer objectContainer) { }

[AfterScenario()]
public static void AfterScenario(IObjectContainer objectContainer) { }

[BeforeScenario()]
public static void BeforeScenario(IObjectContainer objectContainer) { }

All hooks get null injected.

I tried to this code:
args.ObjectContainer.RegisterFactoryAs(() =>
{
var containerBuilderFinder = args.ObjectContainer.Resolve();
var containerBuilder = containerBuilderFinder.GetCreateScenarioContainer();
var container = containerBuilder.Invoke();
return container;
});
into the RegisterGlobalDependencies event and alongside with CustomizeGlobalDependencies but nothing seems to work.

Then I tried to change the signature of the method to this:
public static void BeforeScenario(ITestdependency testDependency). In this case I sometimes get an instance and sometimes still null.

Any help would be usefull, if you want my sourcecode to reproduce things, let me know.

Kind regards,
Danny

@myie-rjenkins
Copy link

myie-rjenkins commented May 4, 2018

I have not used these hooks in our current testing. I have not seen any examples where the hook methods take a parameter (admittedly I haven't investigated much).

Do you need them to be static methods? If you don't then the injection in the constructor would make the object available in the hooks when saved to an instance variable.

If you want the context to be available in a static method I think your best option is to put the windsor container in a static factory so you can reference it and resolve the interfaces

@danny-bos-developer
Copy link
Author

The specflow binding needs them to be static, so I can't make them non-static.

I'm not fond of making a static factory. I will look into our design and see if I can get things to work without using those hooks.

@myie-rjenkins
Copy link

I agree that a static factory is a cludge but I don't believe Windsor will inject into a static method. If you come up with a solution I would be interested in seeing it. I'm sure we will end up using the hooks at some point.

@danny-bos-developer
Copy link
Author

Sure, i'll post a solution when I find one. So far no luck.

@danny-bos-developer
Copy link
Author

Hi Hyie,

I solved the problem by adjusting the Initialize method in the plugin itself like this:

public void Initialize(RuntimePluginEvents runtimePluginEvents, RuntimePluginParameters runtimePluginParameters)
{

        // Wire up our Windsor resolver & container locater to the
        // global IOC container
        runtimePluginEvents.CustomizeGlobalDependencies += (sender, args) =>
        {
            // temporary fix for CustomizeGlobalDependencies called multiple times
            // see https://github.com/techtalk/SpecFlow/issues/948
            if (args.ObjectContainer.IsRegistered<IContainerFinder>()) return;
            args.ObjectContainer.RegisterTypeAs<WindsorResolver, ITestObjectResolver>();
            args.ObjectContainer.RegisterTypeAs<ContainerFinder, IContainerFinder>();
            args.ObjectContainer.RegisterFactoryAs(() =>
            {
                var containerBuilderFinder = args.ObjectContainer.Resolve<IContainerFinder>();
                var containerBuilder = containerBuilderFinder.GetCreateScenarioContainer();
                var container = containerBuilder.Invoke();
                return container;
            });
        };

        // Replace the IOC container with our windsor container
        // which is defined in a method marked with the [ScenarioDependecies] Attribute
        //runtimePluginEvents.CustomizeScenarioDependencies += (sender, args) =>
        //{
        //    args.ObjectContainer.RegisterFactoryAs(() =>
        //    {
        //        var containerBuilderFinder = args.ObjectContainer.Resolve<IContainerFinder>();
        //        var containerBuilder = containerBuilderFinder.GetCreateScenarioContainer();
        //        var container = containerBuilder.Invoke();
        //        return container;
        //    });
        //};
    }

Now the hooks in the steps files are working, you can supply a list of arguments the needs to be injected like this:

[BeforeScenario()]
public static void BeforeScenario(ITestDependency testDependency, ITestDependencyB testDependencyb)
{
// bleh static...
}

    [BeforeScenario()]
    public void BeforeScenarioX(ITestDependency testDependency, , ITestDependencyB testDependencyb)
    {
        // yay non static is working too :D
    }

Only things that don't work are the BeforeFeature and AfterFeature. Then all argument are null. This is not a problem to me, it has to do with the available RuntimePluginEvents; there you only get hooks for global and scenario events, not for feature events. Specflow has some requests to make to available, so maybe in the future we're able to hook up things for the other two hooks.

Hope I gave you enough explanation and you might wanna adjust you're own plugin so the issue can be resolved.

Kind regards
Danny

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants