Skip to content

Add typed setups for IMock<T> - #1727

Merged
kzu merged 11 commits into
mainfrom
typed-setups
Sep 29, 2026
Merged

kzu merged 11 commits into
mainfrom
typed-setups

Conversation

@kzu

@kzu kzu commented Sep 29, 2026 •

Copy link
Copy Markdown
Member

Summary

This replaces the expression-based Mock<T>.Setup surface with typed setups generated for each mocked member.

A setup is the member call itself: calc.Add(2, 3).Returns(5). Syntax.Setup remains for recursive calls and for members that collide with the mock (Object, CallBase). SetupRef covers ref/out members through a custom delegate. Verification is Verify.Called(mock) and Verify.Called(() => ...).

Mock<T> and the additional-interface overloads ship as source in the package, so a test project can customize creation with a partial class. SDK introspection is now IMockRuntime. IMock<T> is the typed mock.

Across the branch

  • An incremental generator emits C# 14 extension members for each mocked type. A generated method setup calls SetupFactory.Capture once. The setup scope and the ambient setup stay behind that call. Properties, indexers, and event raising stay one call each.
  • Returns, Callback, and Throws configure the setup. A typed setup, including SetupRef, passes the member arguments to the handler. A syntax setup (Syntax.Setup) passes the invocation's argument collection. The setup records which path produced it (ITypedSetup.IsTyped), and both verbs apply the handler in one place.
  • Occurrence verbs (Once, Never, Exactly) and Verify run against IMock<T>.
  • The legacy expression Mock<T>, the Of2 prototype, and the hand-written mock types in tests are gone. Tests use the generated setups.
  • Analyzers and code fixes target the new shape: simplify Setup(() => ...) to a typed member, warn when a member hides a mocked member, and offer a custom delegate for ref/out.
  • Acceptance tests for the static and dynamic proxies run in CI against the packed Moq.

kzu added 10 commits September 28, 2026 19:44
…ed mock

- Moq.Sdk.IMock -> IMockRuntime (untyped), IMocked.Mock -> IMocked.Runtime
- DefaultMock -> DefaultMockRuntime, MockDecorator -> MockRuntimeDecorator
- AsMock/Clone/InvocationsFor -> static MockRuntime.Get/TryGet/Clone/InvocationsFor
- Drop Sdk IMock<T> and MockDecorator<T>
- SetupScope is now reentrant (restores previous state on dispose)
- IMoq/IMoq<T> -> Moq.IMock/IMock<T>, Moq<T> -> MockView<T>
- Behavior/DefaultValue/CallBase/Name extension properties on IMockRuntime
- Sdk extension property on IMock returning the runtime
…c Setup/SetupRef and IMock-based Verify

- ISetup<TDelegate>/ISetup<TDelegate,TResult>/ISetupRef<TDelegate> expose the Sdk IMockSetup
- Lazy property and indexer setup handles via SetupFactory, for generated code
- Verbs as extensions on setups rather than on any T, with async unwrapping
- Static Setup(() => ...) fallback with untyped argument collection handlers
- Verify.Called/NotCalled/Calls on IMock<T> return verifier mocks
- Fix argument matchers not applying to ref/out parameters
Extension blocks per mocked type with typed method setups, lazy property and indexer handles, delegate Invoke, RaiseXxx events and custom delegates for ref/out signatures. Mocked types are discovered from [MockGenerator] calls, object creations and class attributes, IMock<T>/Mock<T> references and mock-returning accessors like Mock.Get. Reports MOQ010 below C# 14.
Partial C# and VB classes with v4-style constructors routed through Mock.Create, an OnCreated hook, As<TInterface>() views and Mock.Get<T> overloads returning Mock<T>. The static proxy discovers mocks from [MockGenerator] constructors, and the package defaults LangVersion to latest for C# projects.
Delegate verifiers are bound back to the delegate type, recursive mocks are reused across setups, and the static proxy discovers recursive mocks through Mock.Get(Mock.Of<T>()).
MOQ001 simplifies Setup(() => mock.Object.X(...)) to the generated typed setup, MOQ002 and its code fix set up mocked members hidden by the mock (or skipped by the generator) on the mocked object, the custom delegate fix targets SetupRef, and type validation covers mock constructors and class-level [MockGenerator]. Removes the unused Moq.CodeFix and Moq.Tests.Basic projects.
…the packed Moq

Static covers C# 14 typed setups on compile-time mocks, Dynamic covers the Setup(() => ...) syntax on run-time proxies under C# 8, and Dynamic.Basic covers Visual Basic. They restore Moq only from bin via their own nuget.config into an isolated packages folder.

Also removes Syntax.Verify, which shadowed the Verify class under 'using static Moq.Syntax', stops leaking TypeNameFormatter.Sources to consumers, and fixes a nullable warning in the shipped Mock.cs.
@kzu

kzu commented Sep 29, 2026 •

Copy link
Copy Markdown
Member Author

333 passed 333 passed

🧪 Details on Ubuntu 24.04.5 LTS

from retest v1.1.0 on .NET 10.0.12 with 💜 by @devlooped

@kzu
kzu enabled auto-merge (rebase) September 29, 2026 06:39
@kzu
kzu merged commit f5c8cdd into main Sep 29, 2026
4 checks passed
@kzu
kzu deleted the typed-setups branch September 29, 2026 07:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant