Search code examples
c#moqautomoq

Prevent Moq from creating singleton Mocks


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.


Solution

  • 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));
    }