fix: delegate wrapped calls of hidden interface members to the declaring interface - #847
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes Mockolate’s source generator wrapping behavior for interface members that hide base interface members via new and are emitted as explicit interface implementations. The generator previously cast MockRegistry.Wraps to the mocked type, which could bind the delegated call to the hiding member (wrong return type / constraint issues); this change casts to the declaring interface when method.ExplicitImplementation is set.
Changes:
- Update method wrapping delegation in the source generator to cast
MockRegistry.Wrapstomethod.ExplicitImplementation(when present) instead of the mocked type. - Add runtime test coverage for wrapping hidden generic interface methods.
- Add generator tests covering hidden-method wrapping across constraint/return-type hierarchy variations.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| Tests/Mockolate.Tests/TestHelpers/IChocolateCatalog.cs | Adds interfaces that model a hidden generic method (new) scenario for runtime wrapping tests. |
| Tests/Mockolate.Tests/MockTests.WrappingInterfaceTests.cs | Adds a runtime regression test and helper implementation to validate correct delegation for hidden interface members. |
| Tests/Mockolate.SourceGenerators.Tests/MockTests.cs | Adds generator-level assertions to ensure generated wrapping code casts to the declaring interface for hidden members. |
| Source/Mockolate.SourceGenerators/Sources/Sources.MockClass.cs | Adjusts generated wrapping cast to use method.ExplicitImplementation ?? className for delegation binding correctness. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
🚀 Benchmark ResultsDetails
Details
Details
Details
Details
Details
|
…ing interface A method that hides a base interface member via `new` is emitted as an explicit interface implementation, but its wrapping delegation cast `MockRegistry.Wraps` to the mocked type instead of the declaring interface. The delegated call therefore bound to the hiding member: - same constraints, different return type: wrong member invoked silently - hiding member adds a constraint: CS0452 - hiding member narrows a constraint: CS0453 - three-level hierarchy: CS0266 Cast to `method.ExplicitImplementation` when set, mirroring how events already treat explicitly implemented members.
132f47f to
3945b96
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (1)
Tests/Mockolate.Tests/MockTests.WrappingInterfaceTests.cs:200
- The explicit interface implementation
IChocolateSource.Get<T>()is missing thewhere T : notnullconstraint required byIChocolateSource.Get<T>(). This won’t compile (constraints on an implementing generic method must match the interface method).
IEnumerable<T> IChocolateSource.Get<T>()
{
ReceivedCalls.Add("source");
return [];
}
|
…nterface members to the declaring interface (#847) by Valentin Breuß
…nterface members to the declaring interface (#847) by Valentin Breuß



A method that hides a base interface member via
newis emitted as an explicit interface implementation, but its wrapping delegation castMockRegistry.Wrapsto the mocked type instead of the declaring interface. The delegated call therefore bound to the hiding member:Cast to
method.ExplicitImplementationwhen set, mirroring how events already treat explicitly implemented members.