Prevent Moq from creating singleton Mocks

588 views Asked by At

It seems like mocked services are being shared with consumers, as if the mocked interfaces are singleton. I'm using AutoMoq/Moq combination if that's relevant.

class TestableClass 
{ 
    public IService service; 
    public TestableClass(IService s) { this.service = s }
}

Mocker.GetMock<IService>.Setup(s => s.Do()).Returns(1);
var c1 = Mocker.Resolve<TestableClass>();
var c2 = Mocker.Resolve<TestableClass>();
Assert.That(c1, Is.Not.SameAs(c2)); // true
Assert.That(c1.service, Is.NotSameAs(c2.service)) // false/fail

Is there a way to ensure that IService is a different instance each time a consuming instance is created? The reason being:

Mocker.GetMock<IPauseTimer>()
    .Setup(t => t.Begin(20))
    .Raises(t => t.Tick += null, new PauseTimerEventArgs(1))
    .Verifiable();

When I create my two test instances, they share this single PauseTimer, and when c1 triggers the Begin function, both c1 and c2 react to the event, when only c1 should.

1

There are 1 answers

1
Josh Smeaton On BEST ANSWER

I worked around it by creating another mocking container, which ensures the instances are not the same reference.

var otherMocker = new AutoMoqer();
Mocker.GetMock<IService>.Setup(s => s.Do()).Returns(1);
otherMocker.GetMock<IService>.Setup(s => s.Do()).Returns(1);
var c1 = Mocker.Resolve<TestableClass>();
var c2 = otherMocker.Resolve<TestableClass>();
Assert.That(c1, Is.Not.SameAs(c2)); // true
Assert.That(c1.service, Is.NotSameAs(c2.service)) // true

This is not really desirable, as all the setup work needed to be replicated on this other container. A helper method helps:

[SetUp]
public void Setup()
{
    Mocker = GetMoqer();
}

AutoMoqer GetMoqer() 
{ 
    // configure base Mocker 
    return new AutoMoqer();
}

[Test]
public void TestWithDifferentInstances()
{
    var s1 = Mocker.ResolveMock<IService>();
    var otherMocker = GetMoqer();
    var s2 = otherMocker.ResolveMock<IService>();
    Assert.That(s1, Is.Not.SameAs(s2));
}