Search code examples
c#dependency-injection.net-coremoqfactory-pattern

Mocking multiple instances of interface: Setup of the last mock affects the others


Following my question about conditional-dependency-resolver-on-run-time

I built a BooService that has a injected array of IFooService[], And a FooFactory method that return one of the foo services based on a given key on run time.

class BooService
{
    readonly IFooService[] _fooServices;

    BooService(IFooService[] services)
    {
        this._fooServices = services;
    }
    IFooService FooFactory(Guid id)
    {
        IFooService fooService = Array.Find(this._fooServices, 
                                     service => service.Id == id);
        return fooService;
    }
}

public class FooService1 : IFooService
{
    public int Id { get { return 1; }  
}
public class FooService2 : IFooService
{
    public int Id { get { return 2; }  
}

Everything works OK on run-time but my UnitTests fails:

AutoMock _mock = Autofac.Extras.Moq.AutoMock.GetLoose();
Mock<IFooService> fooService1 = _mock.Mock<IFooService>();
fooService1
    .Setup(x => x.Id)
    .Returns(1);

Mock<IFooService> fooService2 = _mock.Mock<IFooService>();
fooService2
    .Setup(x => x.Id)
    .Returns(2);

IFooService[] fooServices = new IFooService[] { fooService1.Object, fooService2.Object };

BooService booService = new BooService(fooServices);
booService.FooFactory(1); //Result in null
booService.FooFactory(2); //Result in "fooService2"

For the id of 1 the line code of Array.Find(this._fooServices, ...); result in null!

When I comment the creation of the second instance of the mocked interface the code of booService.FooFactory(1); result in fooService1. So I guessing the second Setup affects somehow on the first instance.

Any suggestion why when creating two mocked instance of the interface makes the Array.Find(...) find only last created mocked instance?

If it is a bug in Moq: any clean work around to unit test the find process?


Solution

  • _mock.Mock<IFooService>()
    

    Will return the same mocked instance for each call so the setup is actually being done on one instance. Last setup wins every time.

    Here is the manual approach

    IFooService fooService1 = Mock.Of<IFooService>(_ => _.Id == 1);
    IFooService fooService2 = Mock.Of<IFooService>(_ => _.Id == 2);
    
    IFooService[] fooServices = new IFooService[] { fooService1.Object, fooService2.Object };