C# – Using Moq to verify a parameter of type List<>

cmoq

Using Moq, I'd like to be able to verify that certain conditions are met on a parameter being passed to a mocked method call. In this scenario, I'd like to check that the list passed into the mocked method is of a certain size:

var mockSomeRepository = new Mock<SomeRepository>();
mockSomeRepository.Setup(m => m.Write(It.IsAny<List<SomeDTO>>())).Verifiable();

var mainClass = new MainClass(mockSomeRepository.Object);
List<SomeDTO> someList = GetListWith25Items();

mainClass.DoRepositoryWrite(someList); // calls SomeRepository.Write(someList);

mockSomeRepository.Verify(m => 
    m.Write(It.Is<List<SomeDTO>>(l => l.Count() == 25)), Times.Once());

The verify assert throws an exception that says the method is never called in this fashion. However, removing the constraint and using Is.Any<List<SomeDTO>>() instead leads to a pass. I'm not sure if I'm using It.Is<>() properly here – this is what I intuitively want my test to look like but I'm not sure if I'm using the framework properly. How should I properly frame this test?

Best Answer

You can get rid of the call to Setup and Verifiable on your mock. Just use Verify.

I created a little test-project, and this worked for me:

using System;
using System.Collections.Generic;
using System.Linq;
using Moq;

namespace csharp
{
    public class SomeDTO { }

    public class SomeRepository { public virtual void Write(List<SomeDTO> list) { } }

    public class MainClass
    {
        private SomeRepository someRepository;

        public MainClass(SomeRepository someRepository) { this.someRepository = someRepository; }

        public void DoRepositoryWrite(List<SomeDTO> list) { this.someRepository.Write(list); }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var mockSomeRepository = new Mock<SomeRepository>();
            var someList = Enumerable.Repeat(new SomeDTO(), 25).ToList();

            var mainClass = new MainClass(mockSomeRepository.Object);
            mainClass.DoRepositoryWrite(someList);

            mockSomeRepository.Verify(m => m.Write(It.IsAny<List<SomeDTO>>()), Times.Once(), "Write was not called");
            mockSomeRepository.Verify(m => m.Write(It.Is<List<SomeDTO>>(l => l.Count == 25)), Times.Once(), "Write was not called with a 25-element-list");
        }
    }
}