BanksySan
BanksySan

Reputation: 28560

Using Moq with Linq Any()

I have a setup similar to below:

    [TestMethod]
    public void NoIntegers()
    {
        Mock<IBar> mockBar = new Mock<IBar>(MockBehavior.Strict);
        Mock<IEnumerable<int>> mockIntegers = new Mock<IEnumerable<int>>(MockBehavior.Strict);

        mockBar
            .SetupGet(x => x.Integers)
            .Returns(mockIntegers.Object);

        mockIntegers
            .Setup(x => x.Any())
            .Returns(false);

        Assert.IsFalse(new Foo(mockBar.Object).AreThereIntegers());
    }

    public interface IBar
    {
        IEnumerable<int> Integers { get; }
    }

    public class Foo
    {
        private IBar _bar;

        public Foo(IBar bar)
        {
            _bar = bar;
        }

        public bool AreThereIntegers()
        {
            return _bar.Integers.Any();
        }
    }
}

When it runs it fails to initialise the mock

Test method NoIntegers threw exception: System.NotSupportedException: Expression references a method that does not belong to the mocked object: x => x.Any<Int32>()

I have tries adding It.IsAny() in a few forms:

mockIntegers
    .Setup(x => x.Any(It.IsAny<IEnumerable<int>>(), It.IsAny<Func<int, bool>>()))
    .Returns(false);

// No method with this signiture


mockIntegers
    .Setup(x => x.Any(It.IsAny<Func<int, bool>>()))
    .Returns(false);

// Throws: Test method NoIntegers threw exception: 
// System.NotSupportedException: 
// Expression references a method that does not belong to the mocked object:
//  x => x.Any<Int32>(It.IsAny<Func`2>())

What do I need to mock in order for this to run?

Upvotes: 6

Views: 4858

Answers (3)

Ufuk Hacıoğulları
Ufuk Hacıoğulları

Reputation: 38508

You need to mock Integers property only. There is no need to mock Any() (you can't do it anyway because it's an extension method) because it is a part of SUT. Here's how you should do it for two cases:

[TestMethod]
public void NoIntegers()
{
    Mock<IBar> mockBar = new Mock<IBar>(MockBehavior.Strict);

    mockBar.SetupGet(x => x.Integers)
           .Returns(new List<int>());

    Assert.IsFalse(new Foo(mockBar.Object).AreThereIntegers());
}

[TestMethod]
public void HasIntegers()
{
    Mock<IBar> mockBar = new Mock<IBar>(MockBehavior.Strict);

    mockBar.SetupGet(x => x.Integers)
           .Returns(new List<int>{ 3, 5, 6});

    Assert.IsTrue(new Foo(mockBar.Object).AreThereIntegers());
}

Upvotes: 2

BanksySan
BanksySan

Reputation: 28560

Fixed!

Not pretty, but this is the mocking that's needed:

   [TestMethod]
    public void NoIntegers()
    {
        Mock<IBar> mockBar = new Mock<IBar>(MockBehavior.Strict);
        Mock<IEnumerable<int>> mockIntegers = new Mock<IEnumerable<int>>(MockBehavior.Strict);
        Mock<IEnumerator<int>> mockEnumerator = new Mock<IEnumerator<int>>(MockBehavior.Strict);
        mockBar
            .SetupGet(x => x.Integers)
            .Returns(mockIntegers.Object);

        mockIntegers
            .Setup(x => x.GetEnumerator())
            .Returns(mockEnumerator.Object);

        mockEnumerator.Setup(x => x.MoveNext()).Returns(false);

        mockEnumerator.Setup(x => x.Dispose());

        Assert.IsFalse(new Foo(mockBar.Object).AreThereIntegers());
    }

    public interface IBar
    {
        IEnumerable<int> Integers { get; }
    }

    public class Foo
    {
        private IBar _bar;

        public Foo(IBar bar)
        {
            _bar = bar;
        }

        public bool AreThereIntegers()
        {
            return _bar.Integers.Any();
        }
    }

Upvotes: 4

Cristian Lupascu
Cristian Lupascu

Reputation: 40576

It does not work because the Any() method is not directly exposed by the IEnumerable<T> interface, but it is defined as an extension method on Enumerable.

I don't think you can set up a call to Any() on any mock, because it is essentially a static method.

In this case I think it's preferable to use an instance of IEnumerable<int> (ex: an int array) that can be set up to be empty/non-empty, depending on what you are testing.

Upvotes: 1

Related Questions