Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moq verify fails when SelectMany

I am using NUnit, Moq and StructureMap.

I have a following NUnit test:

    [Test]
    public void ShouldCallCustomMethod_ForAllICustomInterfaceMocks()
    {
        var customInterfaceMock1 = new Mock<ICustomInterface>();
        var customInterfaceMock2 = new Mock<ICustomInterface>();

        ObjectFactory.Inject(customInterfaceMock1.Object);
        ObjectFactory.Inject(customInterfaceMock2.Object);

        var sut = new SUT();
        sut.MethodThatShouldCallCustomMethodOnMocks();

        customInterfaceMock1.Verify(m => m.CustomMethod());
        customInterfaceMock2.Verify(m => m.CustomMethod());
    }

ICustomInterface:

public interface ICustomInterface
{
    IEnumerable<Type> CustomMethod();
}

Now if implementation of SUT class looks like this:

public class SUT
{
    public IEnumerable<Type> MethodThatShouldCallCustomMethodOnMocks()
    {
        var result = ObjectFactory.GetAllInstances<ICustomInterface>()
             .SelectMany(i => i.CustomMethod());


        return result;
    }
}

test from above fails due to method CustomMethod not being called on mocks. However, if I change implementation of SUT class to this:

public class SUT
{
    public IEnumerable<Type> MethodThatShouldCallCustomMethodOnMocks()
    {
        var customInterfaceInstances = ObjectFactory.GetAllInstances<ICustomInterface>();

        foreach (var instance in customInterfaceInstances)
              instance.CustomMethod();


        return ...
    }
}

test passes! The difference is that instead of iterating with SelectMany i use foreach, but test results differ (in second case CustomMethods do get called on mocks).

Can somebody explain that behaviour?

like image 810
Jarek Mazur Avatar asked Feb 14 '23 16:02

Jarek Mazur


1 Answers

I think this might be a case of deferred execution. SelectMany doesn't execute immediately. The IEnumerable that's returned must be enumerated for your methods to be called. Try adding ToList() after the SelectMany() method to force the IEnumerable returned from SelectMany to be evaluated.

like image 189
Chris Mantle Avatar answered Feb 20 '23 05:02

Chris Mantle