Home > database >  How to substitute Prism ContainerLocator.Container in NUnit
How to substitute Prism ContainerLocator.Container in NUnit

Time:11-11

I have the following code in my class under testing:

  devices = ContainerLocator.Container.Resolve<IDevicesList>();           [1]

In test method I'm trying to write:

 var fakeDeviceList = Substitute.For<IDevicesList>();
 Substitute.For<IContainerProvider>().Resolve<IDevicesList>().Returns(fakeDeviceList);

but I got a null reference exception for ContainerLocator.Container in line [1]. I tried to use

var provider = Substitute.For<IContainerProvider>();
ContainerLocator.Container.Returns(provider);
provider.Resolve<IDevicesList>().Returns(fakeDeviceList);

but got an exception during test run:

Message: 
NSubstitute.Exceptions.CouldNotSetReturnDueToNoLastCallException : Could not find a call to return from.

So my question is how could I make a substitution for ContainerLocator.Container? Thank you in advance.

CodePudding user response:

I have the following code in my class under testing:

devices = ContainerLocator.Container.Resolve<IDevicesList>();

That's the reason why you don't inject the container. In fact, you avoid using the container at all except during the registration phase and the initial call to Resolve.

So my question is how could I make a substitution for ContainerLocator.Container?

The answer's: you don't

What you should do instead is to let the container do the resolving work by injecting what you actually want, not the almighty container.

internal class MyService
{
    public MyService( IDeviceList devices )
    {
    }
}

or

internal class MyService
{
    public MyService( IEnumerable<IDevice> devices )
    {
    }
}

or

internal class MyService
{
    public MyService( Lazy<IEnumerable<IDevice>> devices )
    {
    }
}

or

internal class MyService
{
    public MyService( IEnumerable<Lazy<IDevice>> devices )
    {
    }
}

The differences between injecting a Lazy<IEnumerable> and a IEnumerable<Lazy> are subtle and depend on the actual container used, the behavior of the IContainerProvider is undefined in general in this case.

Anyway, you can easily inject the mocked devices in this way without having to mock the container or even use the real container during testing.

  • Related