Mock.Verify uses current value of list, not the value of the list when the method being verified was called

Viewed 41

I have a situation where I'm running a unit test and calling Verify to assert that a method was called using a non-empty list as a parameter. The method being tested calls Clear() on the list at the end of the method. It seems like when Verify is called, it's checking the state of the list at the current time, not at the time when my function was called. Is that the expected behavior and is there any way to have Verify use the value of the list at the time that my method was called?

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System.Linq;
using System.Collections.Generic;

namespace Tests
{
    [TestClass]
    public class UnitTest1
    {
        public interface IMyDependency
        {
            void ParseNumbers(List<int> numbers);
        }

        public class MyDependency : IMyDependency
        {
            public void ParseNumbers(List<int> numbers)
            {
            }
        }

        public class SystemUnderTest
        {
            private IMyDependency myDependency;

            public SystemUnderTest(IMyDependency myDependency)
            {
                this.myDependency = myDependency;
            }

            public void DoSomething(List<int> numbers)
            {
                this.myDependency.ParseNumbers(numbers);

                // This causes my test to fail because Verify thinks that ParseNumbers was called
                // with an empty list as the parameter, even though the list was not empty when
                // ParseNumbers was called
                numbers.Clear();
            }
        }

        [TestMethod]
        public void TestMethod1()
        {
            var myDependency = new Mock<IMyDependency>();
            var systemUnderTest = new SystemUnderTest(myDependency.Object);

            systemUnderTest.DoSomething(new List<int> { 1, 2, 3 });

            // This succeeds
            myDependency.Verify(e => e.ParseNumbers(It.IsAny<List<int>>()), Times.Once);
        
            // This fails
            myDependency.Verify(e => e.ParseNumbers(It.Is<List<int>>(m => m.Count > 0)), Times.Once);
        }
    }
}
1 Answers

Is that the expected behavior

Looks like that behavior might be a bug. I would suggest raising an issue with the developer.

and is there any way to have Verify use the value of the list at the time that my method was called?

Make the setup Verifiable

[TestMethod]
public void TestMethod1() {
    // Arrange
    var myDependency = new Mock<IMyDependency>();
    myDependency
        .Setup(e => e.ParseNumbers(It.Is<List<int>>(m => m.Count > 0)))
        .Verifiable(); //<-- MAKE SETUP VERIFIABLE

    var systemUnderTest = new SystemUnderTest(myDependency.Object);

    // Act
    systemUnderTest.DoSomething(new List<int> { 1, 2, 3 });

    // Assert
    myDependency.Verify(); // Verifies that all verifiable expectations have been met.
}
Related