7

I have a repository with an Add method that takes an IEnumerable as parameter:

public void Add<T>(T item) where T : class, new(){}

In a unittest I want to verify that this method is called with an IEnumerable that contains exactly the same amount of elements as another IEnumerable

[Test]
public void InvoicesAreGeneratedForAllStudents()
{
    var students = StudentStub.GetStudents();
    session.Setup(x => x.All<Student>()).Returns(students.AsQueryable());

    service.GenerateInvoices(Payments.Jaar, DateTime.Now); 

    session.Verify(x => x.Add(It.Is<IEnumerable<Invoice>>(
        invoices => invoices.Count() == students.Count())));
 }

Result of the unit test:

Moq.MockException : 
Expected invocation on the mock at least once, but was never performed: 

x => x.Add<Invoice>(It.Is<IEnumerable`1>(i => i.Count<Invoice>() == 10))

No setups configured.

What am I doing wrong?

Andrew
  • 5,395
  • 1
  • 27
  • 47

1 Answers1

4

From your code example you haven't set up the x => x.Add on the Moq

session.Setup(x => x.Add(It.IsAny<IEnumerable>());

Unless the Setup for x.All is meant to be x.Add? If so, you need to match the Verify and Setup exactly - a good way to do that is to extract it to a common method that returns an Expression.

EDIT: Added a sample, I have changed the signature of Add as I can't see how you could pass a collection otherwise.

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        Mock<Boo> moqBoo = new Mock<Boo>();
        moqBoo.Setup(IEnumerableHasExpectedNumberOfElements(10));

        // ACT

        moqBoo.Verify(IEnumerableHasExpectedNumberOfElements(10));
    }

    private static Expression<Action<Boo>> IEnumerableHasExpectedNumberOfElements(int expectedNumberOfElements)
    {
        return b => b.Add(It.Is<IEnumerable<Invoice>>(ie => ie.Count() == expectedNumberOfElements));
    }
}

public class Boo
{
    public void Add<T>(IEnumerable<T> item) where T : class, new()
    {
    }
}

public class Invoice
{

}

Also, a good way to debug these things is to set your Mock up with MockBehavior.Strict and then you'll be informed by the invoked code what you need to configure.

Ciaran
  • 541
  • 2
  • 11