jeudi 26 septembre 2019

How to create a Spec-Flow test for a Prism 7 app?

I'm in the process of creating a new windows desktop app with Prism 7, and I started out with the new PrismApplication base class that replaced the bootstrapper. Everything was fine until I created the (specflow-)tests.

I was used to re-using the original bootstrapper during initialization of the test-app, just modifying the registrations afterwards. That, transformed to the new Application derived system looks like this:

internal partial class App
{
    protected override IContainerExtension CreateContainerExtension()
    {
        var containerExtension = new Prism.Unity.Ioc.UnityContainerExtension();
        containerExtension.Instance.AddExtension( new LogExtension() );
        return containerExtension;
    }

    protected override Window CreateShell()
    {
        return Container.Resolve<MainWindow>();
    }

    protected override void RegisterTypes( IContainerRegistry containerRegistry )
    {
        containerRegistry.Register<IConfiguration, AppSettingsConfiguration>();
        containerRegistry.Register<IWindowsInterface, WindowsInterface>();
        // ... a lot of registrations removed here ...
    }
}

And a derived test-app that does everything but create the shell:

private class MyApp : App
{
    protected override Window CreateShell()
    {
        return null;
    }
}

Wrapped up in a BeforeScenario hook to initialize the test-app:

[BeforeScenario]
public void InitializeApp()
{
    var app = new MyApp();
    app.Initialize();
    var containerRegistry = (IContainerRegistry)app.Container;

    containerRegistry.RegisterSingleton<TestWindowsInterface>();
    containerRegistry.Register<IWindowsInterface,TestWindowsInterface>();
    // ... some registration overrides removed here ...

    _objectContainer.RegisterInstanceAs<App>( app );
}

And a step to create the main window (CreateShell replacement):

[When( @"I start the software" )]
public void WhenIStartTheSoftware()
{
    _container.RegisterInstanceAs( _container.Resolve<App>().Container.Resolve<MainWindowViewModel>() );
}

So far, so good, this works. But only as long as you have just one scenario. As soon as the second scenario starts, we get an exception:

Cannot create more than one System.Windows.Application instance in the same AppDomain.

In the old days, this wasn't a problem, because the Bootstrapper was just a regular class, as opposed to the PrismApplication which is enforced to be a singleton by the framework.

Of course, I can move the whole registration stuff into a regular class, and use that to initialize the test-app, but this means essentially creating my own version of the bootstrapper on top of the PrismApplication. Using the classic Bootstrapper makes more sense to me, yet it will be dropped in a future release (as it's marked obsolete today).

Is there any official guide or unofficial statement from the Prism team on how to test applications built with the new style?

Aucun commentaire:

Enregistrer un commentaire