Repository navigation
mock.Protected().Setup<int>("Foo") fails base implementation of Foo is hidden in the derived class - #1342
mock.Protected().Setup<int>("Foo") fails base implementation of Foo is hidden in the derived class#1342VladimirKhvostov wants to merge 2293 commits into
Conversation
Always record calls to += and -= event accessors
... by matching and executing setups before event (un-) subscription is dealt with. This has the added benefit of making the interception pipeline more efficient for almost all invocations.
because by the time we get to `HandleEventSubscription`, any setups would already have executed.
Simplify event subscription and remove a remaining inconsistency
Enable parameterized `Mock.Of<>` in query comprehension `from` clause
Discord has several benefits over gitter and is now the de-facto place for other Microsoft large-scale projects (i.e. https://cs.dotnet.gg/) I'm there now most of the time, so selfishly, I'd like to move this over too :)
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.
Add support for nested type matchers
The SolutionDir property is only available when building from the solution. For packing, it's actually not necessary and we could also easily allow packing from the Moq.csproj project itself. This change, in addition to enabling that, also makes the icon path more flexible since it could be moved down to the src folder (say) without requiring a change to the .csproj.
Since we're generating portable symbols, these are WAY smaller than full PDBs used to be. Their size contribution to the package are negligible and for convenience, it's more common nowadays to just embed the symbols always in the assembly itself. In particular for a library that is not deployed to production apps, this makes perfect sense. So stop generating the (effectively legacy) .snupkg.
# devlooped/oss - Don't fail on background workflows devlooped/oss@f08c3f2 # devlooped/.github
Add `Mock<T>.RaiseAsync`
Add `setup.Verifiable(Times times, [string failMessage])` method
…1322) * Project: Convert 'PackageLicenseUrl' to 'PackageLicenseExpression' * Project: Add 'Copyright' as specified in license
…generic-non-void-method Don't throw away generic type arguments in one `mock.Protected().Verify<T>()` method overload
|
|
…s hidden in the derived class (devlooped#1341)
|
Thanks for the PR! Could you rebase on top of main, since files moved around? |
stakx
left a comment
There was a problem hiding this comment.
I haven't reviewed & tested this in detail TBH, but it generally looks good to me.
The changelog should be first updated with the latest few missing releases though, otherwise the changelog entry will end up with an incorrect (already published) version.
There was a problem hiding this comment.
Pull Request Overview
This PR addresses issue #1341 by improving how ProtectedMock selects hidden virtual methods and adds tests to cover this scenario.
- Adjusted
GetMethodlogic to prefer methods declared in derived classes when multiple matches exist. - Added a new test (
SetupResultAllowsHiddenVirtualMethods) to verify setup of hidden protected methods. - Updated changelog to document the fix.
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| tests/Moq.Tests/ProtectedMockFixture.cs | Added a test verifying setup of hidden protected methods. |
| src/Moq/Protected/ProtectedMock.cs | Enhanced method resolution logic for hidden virtual methods. |
| CHANGELOG.md | Documented the fix in the Unreleased fixed section. |
|
|
||
| for (Type type = typeof(T); type != typeof(object); type = type.BaseType) | ||
| { | ||
| var method = methods.SingleOrDefault(m => m.DeclaringType == typeof(T)); |
There was a problem hiding this comment.
The loop variable type is never used: the predicate always checks DeclaringType == typeof(T). It should use the loop variable type (m.DeclaringType == type) to correctly select the most derived declaring type.
| var method = methods.SingleOrDefault(m => m.DeclaringType == typeof(T)); | |
| var method = methods.SingleOrDefault(m => m.DeclaringType == type); |
| methods = methods.Where(m => m.GetParameterTypes().CompareTo(argTypes, exact, considerTypeMatchers: false)); | ||
|
|
||
| if (methods.Count() < 2) |
There was a problem hiding this comment.
Calling Count() on an IEnumerable will enumerate it; since it's used again below, consider materializing methods into a collection (e.g., var list = methods.ToList()) to avoid multiple enumerations.
| methods = methods.Where(m => m.GetParameterTypes().CompareTo(argTypes, exact, considerTypeMatchers: false)); | |
| if (methods.Count() < 2) | |
| methods = methods.Where(m => m.GetParameterTypes().CompareTo(argTypes, exact, considerTypeMatchers: false)).ToList(); | |
| if (methods.Count < 2) |
This PR fixes an issue described in the #1341