Moq Verify Without It - what to compare?

When using Moq with Verify to assert that a particular method has been called with the specified parameters, a different syntax is possible; one is the syntax of "This," like this

mock.Verify(c => c.SomeMethod(It.Is<string>(s => s == ExpectedString))); 

What happens here is that the parameter that SomeMethod is called SomeMethod is checked for equality with ExpectedString . Another possible syntax without "It":

 mock.Verify(c => c.SomeMethod(ExpectedString)); 

which should give the same result. From what I could find on different forums, the difference is that the latter is an identification check (reference values) (except for value types).

However, my question is when the parameter is of type of type Collection. In .NET, Equals on Collection<T> just inherited from object , so check the following:

 mock.Verify(c => c.SomeMethod(new Collection<string> { ExpectedString })); 

cannot be transferred, given that the assembly is created as a result of verification and, therefore, cannot be the same instance that is created in the production code. However, it works, which indicates that Moq is doing CollectionAssert or something like that, unlike the information I could find.

Here is an example of code that illustrates the behavior of a test passing, but I think it should fail if Moq used link comparison equal.

 [TestMethod] public void Test() { var mock = new Mock<IPrint>(); const int ExpectedParam = 1; var test = new TestPrinter { Printer = mock.Object, Expected = ExpectedParam }; test.Do(); mock.Verify(c => c.Print(new Collection<int> { ExpectedParam })); } public interface IPrint { void Print(Collection<int> numbers); } public class TestPrinter { public IPrint Printer { get; set; } public int Expected { get; set; } public void Do() { Printer.Print(new Collection<int> { Expected }); } } 

Does anyone know if this is the expected Moq behavior (version 4.1)? Has the behavior been changed at some version level?

+6
source share
1 answer

This is the desired behavior and added to moq in January 2009 (version 3.0.203.1).

If moq finds IEnumerable , it uses SequenceEqual to compare the actual argument and the argument used in the setup, otherwise it just uses Equals .

Here is the corresponding bit of code:

 internal class ConstantMatcher : IMatcher { ... public bool Matches(object value) { if (object.Equals(constantValue, value)) { return true; } if (this.constantValue is IEnumerable && value is IEnumerable) { return this.MatchesEnumerable(value); } return false; } private bool MatchesEnumerable(object value) { var constValues = (IEnumerable)constantValue; var values = (IEnumerable)value; return constValues.Cast<object>().SequenceEqual(values.Cast<object>()); } } 
+5
source

Source: https://habr.com/ru/post/971330/


All Articles