Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for nested type matchers #1092

Merged
merged 6 commits into from Nov 1, 2020

Conversation

stakx
Copy link
Contributor

@stakx stakx commented Nov 1, 2020

Closes #919.

@stakx stakx added this to the 4.15.0 milestone Nov 1, 2020
src/Moq/Extensions.cs Outdated Show resolved Hide resolved
src/Moq/Extensions.cs Show resolved Hide resolved
src/Moq/Extensions.cs Outdated Show resolved Hide resolved
src/Moq/Extensions.cs Outdated Show resolved Hide resolved
Comment on lines +67 to +68
mock.Setup(m => m.Method<It.IsAnyType>(It.IsAny<IEnumerable<It.IsAnyType>>())).Verifiable();
mock.Object.Method(new string[] { "a", "b" });
Copy link
Contributor Author

@stakx stakx Nov 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not actually sure I understand why this should work, given the previous tests for SubstituteTypeMatchers. Would this successfully match a string[] (runtime type) or a IEnumerable<string> (static compile-time type) against IEnumerable<It.IsAnyType>? Need to investigate.

When testing an argument's type against a "template type" that may in-
volve type matchers, we can no longer do a simple `IsAssignableFrom`;
we'd have to create our own type matcher-aware version of it that com-
pares each constituent part of both sides' types (visited in lockstep).

Implementing our own `IsAssignableFrom` is going to be quite difficult
because we also have to account for variance. Looking at both ECMA-335
and .NET Core's source code, that looks rather complex... let's not go
there.

What we'll do instead is much easier: we still visit both sides' types'
constituent parts, and whenever we encounter a type matcher in the
template type, we test it against the corresponding (sub-) type from
the argument. If it's a match, we substitute the argument type in the
template type. If all type matchers match, we end up with a rewritten
template type that no longer uses any matchers; we can then use `Is-
AssignableFrom` with _that_ template type and the argument type to let
the framework deal with variance.
The `Microsoft.Extensions.Logging.Abstractions.ILogger` scenario is one
that many people have shown interest in, so let's cover that one in
particular.
@stakx stakx merged commit 9fcf8a0 into devlooped:master Nov 1, 2020
@stakx stakx deleted the nested-type-matchers branch November 1, 2020 13:31
mburumaxwell pushed a commit to faluapp/falu-dotnet that referenced this pull request Jun 12, 2021
Bumps [Moq](https://github.com/moq/moq4) from 4.14.7 to 4.15.2.

#Changelog

*Sourced from [Moq's changelog](https://github.com/moq/moq4/blob/master/CHANGELOG.md).*

> ## 4.15.2 (2020-11-26)
>
> #### Changed
>
> * Upgraded `System.Threading.Tasks.Extensions` dependency to version 4.5.4 (@JeffAshton, [#1108](devlooped/moq#1108))
>
>
> ## 4.15.1 (2020-11-10)
>
> #### Added
>
> * New method overloads for `It.Is`, `It.IsIn`, and `It.IsNotIn` that compare values using a custom `IEqualityComparer<T>` (@weitzhandler, [#1064](devlooped/moq#1064))
> * New properties `ReturnValue` and `Exception` on `IInvocation` to query recorded invocations return values or exceptions (@MaStr11, [#921](devlooped/moq#921), [#1077](devlooped/moq#1077))
> * Support for "nested" type matchers, i.e. type matchers that appear as part of a composite type (such as `It.IsAnyType[]` or `Func<It.IsAnyType, bool>`). Argument match expressions like `It.IsAny<Func<It.IsAnyType, bool>>()` should now work as expected, whereas they previously didn't. In this particular example, you should no longer need a workaround like `(Func<It.IsAnyType, bool>)It.IsAny<object>()` as originally suggested in [#918](devlooped/moq#918). (@stakx, [#1092](devlooped/moq#1092))
>
> #### Changed
>
> * Event accessor calls (`+=` and `-=`) now get consistently recorded in `Mock.Invocations`. This previously wasn't the case for backwards compatibility with `VerifyNoOtherCalls` (which got implemented before it was possible to check them using `Verify{Add,Remove}`). You now need to explicitly verify expected calls to event accessors prior to `VerifyNoOtherCalls`. Verification of `+=` and `-=` now works regardless of whether or not you set those up (which makes it consistent with how verification usually works). (@80O, @stakx, [#1058](devlooped/moq#1058), [#1084](devlooped/moq#1084))
> * Portable PDB (debugging symbols) are now embedded in the main library instead of being published as a separate NuGet symbols package (`.snupkg) (@kzu, [#1098](devlooped/moq#1098))
>
> #### Fixed
>
> * `SetupProperty` fails if property getter and setter are not both defined in mocked type (@stakx, [#1017](devlooped/moq#1017))
> * Expression tree argument not matched when it contains a captured variable &ndash; evaluate all captures to their current values when comparing two expression trees (@QTom01, [#1054](devlooped/moq#1054))
> * Failure when parameterized `Mock.Of<>` is used in query comprehension `from` clause (@stakx, [#982](devlooped/moq#982))
>
>
> ## 4.15.0
>
> This version was accidentally published as 4.15.1 due to an intermittent problem with NuGet publishing.

#Commits

- [`f2aa090`](devlooped/moq@f2aa090) ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for nested type matchers
1 participant