You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
TUnit.Mocks: generic-method setups with explicit type arguments do not bind on Mock.Of<IGeneric<X>>() #7302
On a Mock<T> returned by Mock.Of<IGeneric<X>>(), a setup for a generic method fails with CS1061 when the call passes explicit method type arguments. The same call compiles on the typed wrapper that IGeneric<X>.Mock() returns. It also compiles on Mock.Of when the method type arguments can be inferred.
Found while working on #7299. It happens on main without that change, with no type parameter name collision.
Repro (TUnit.Mocks.Tests, net10.0)
Uses the existing IGenericKitchenSink<TItem, TValue> in tests/TUnit.Mocks.Tests/KitchenSinkGenericTests.cs, which declares TState RoundTrip<TState>(TState state) where TState : struct:
error CS1061: 'Mock<IGenericKitchenSink<GenericPayload, int>>' does not contain a definition for 'RoundTrip' and no accessible extension method 'RoundTrip' accepting a first argument of type 'Mock<IGenericKitchenSink<GenericPayload, int>>' could be found
The generator emits the member in both extension blocks with the same shape:
extension<TItem,TValue>(global::TUnit.Mocks.Mock<global::TUnit.Mocks.Tests.IGenericKitchenSink<TItem,TValue>>mock)whereTItem:class{
public ..._RoundTrip_M9_MockCall<TState,TItem,TValue>RoundTrip<TState>(global::TUnit.Mocks.Arguments.Arg<TState>state)where TState :struct
and
extension<TItem,TValue>(global::TUnit.Mocks.Tests.IGenericKitchenSink_TItem_TValue_Mock<TItem,TValue>mock)whereTItem: class
Only the Mock<...> receiver fails to bind when explicit type arguments are present. A method whose type parameter appears only in the return type, such as T Invoke<T>(object message), therefore cannot be set up through Mock.Of<IGeneric<X>>() at all.
Expected
Mock.Of<IGeneric<X>>().Method<Y>(...) binds the same way as it does on the typed wrapper. If this is a compiler limitation of extension-block type inference, the generator should emit a shape that binds, for example a non-generic-receiver overload per closed registration, or the docs should steer users to .Mock().
Activity
fix(mocks): omit colliding closed setup overloads (#7302)
fix(mocks): normalize closed signatures without recursive substitution (
docs(mocks): explain emitted signature collision checks (#7302)
docs(mocks): link setup emitter to collision analysis (#7302)
fix(mocks): guard closed setup analysis against emitter drift (#7302)