Verification of list parameters

I'm trying to verify a call was made to a repository AddRange method. I can verify the method was called at all like this:
```
GetMockFor<IThingRepository>()
.Verify(x => x.AddRange(It.IsAny<IEnumerable<Thing>>()), Times.Once);
```
I can verify that it was passed the expected two objects using some of Moq's partial matching like this:
```
GetMockFor<IThingRepository>()
.Verify(x => x.AddRange(It.Is<IEnumerable<Thing>>(y =>
y.Count() == 2
&& y.Any(z => z.ThingType == ThingType.Foo)
&& y.Any(z => z.ThingType == ThingType.Bar))));
```
What I can't seem to do is get it to work using a more understandable partial matching syntax like this:
```
GetMockFor<IThingRepository>()
.Verify(x => x.AddRange(Looks.Like(() => new[]
{
new Thing {ThingType = ThingType.Foo},
new Thing {ThingType = ThingType.Bar},
})));
```
In every case, the code runs but the verify fails saying the method was never called. I looked through the documentation examples, and while they cover the partial matching functionality, they don't have an example of partial matching a collection of things like this. I know the partial matching can do hierarchies, but what about collections?
I've even tried replacing the objects in the list with their own individual Looks.Likes:
```
GetMockFor<IThingRepository>()
.Verify(x => x.AddRange(
Looks.Like(() => new[]
{
Looks.Like(()=>new Thing {ThingType = ThingType.Foo}),
Looks.Like(()=>new Thing {ThingType = ThingType.Bar}),
})));
```
Because of the way this particular code is written, the order of the elements being added is predictable, so I've eliminated that variable, although a partial match that could ignore ordering would be pretty awesome.
What am I doing wrong here?

In any case, this seems to be a bug in Looks.Like(), I just need to figure out the exact scenario so I can fix it.

Mel Grubb

Mar 3, 2016

Aha, that's it. AddRange is being passed an IEnumerable which is the result of an EF/Linq query, so it's technically and ObjectSet<T> at that point. I can see that throwing off the Looks.Like since the two enumerables are not the same type.

It would be acceptable to call ToArray or ToList on the collection before calling AddRange, since it will enumerate at that point anyway. I just tested it this way, and now the test works.

So the scenario is that Looks.Like sees an array on the one side, an ObjectSet<T> on the other, and decides that they're dissimilar enough to call it quits right then. I don't know what's going on behind the scenes here, but unless Looks.Like has some way to figure out that the method being called wanted any kind of IEnumerable, and can take that into account when comparing the two objects, I'd say this is a matter for documentation rather than code.

Thanks.

Matt Honeycutt

Mar 3, 2016

I'd like to make the partial matching handle this better. It should already know that both ends of the call are compatible enumerables since the compiler will enforce that. At the very least, it should throw a more useful exception.

I'd like to make the partial matching handle this better. It should already know that both ends of the call are compatible enumerables since the compiler will enforce that. At the very least, it should throw a more useful exception.