Repository navigation
feat(mocks): TM010 analyzer + code fix for Mock.Of<T>() -> T.Mock() - #7307
Conversation
…ck() Adds a TUnit.Mocks.Analyzers.CodeFixers project bundled into the TUnit.Mocks package. TM010 (Info) reports Mock.Of<T>() and Mock.Of<T>(behavior) calls that can use the generated T.Mock() / T.Mock(behavior) extension, and the code fix rewrites them, adding `using TUnit.Mocks;` when needed. Co-Authored-By: Claude <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Diagnostic and eligibility analysis src/TUnit.Mocks.Analyzers/DiagnosticIds.cs, src/TUnit.Mocks.Analyzers/Rules.cs, src/TUnit.Mocks.Analyzers/PreferStaticMockSyntaxAnalyzer.cs, src/TUnit.Mocks.SourceGenerator/Diagnostics.cs |
Adds diagnostic ID constants and the TM010 descriptor. The analyzer reports eligible calls for C# 14 or later and excludes unsupported calls, types, and contexts. |
Code fix and package integration src/TUnit.Mocks.Analyzers.CodeFixers/*, src/TUnit.Mocks/TUnit.Mocks.csproj, TUnit.slnx, TUnit.CI.slnx, TUnit.Dev.slnx, docs/docs/writing-tests/mocking/index.md |
Adds a fix that rewrites supported calls to T.Mock() and adds using TUnit.Mocks; when needed. Adds the code-fix project to the solutions and package, and documents the diagnostic and fix-all options. |
Analyzer and code-fix validation tests/TUnit.Mocks.Analyzers.Tests/* |
Adds tests for supported rewrites, excluded cases, and rules decoupling. Adds test helpers for code-fix verification and line-ending normalization. |
Estimated code review effort: 3 (Moderate) | ~25 minutes
Change: Feature
Sequence Diagram(s)
sequenceDiagram
participant Developer
participant PreferStaticMockSyntaxAnalyzer
participant PreferStaticMockSyntaxCodeFixProvider
participant RoslynDocument
Developer->>PreferStaticMockSyntaxAnalyzer: Provide source with Mock.Of<T>()
PreferStaticMockSyntaxAnalyzer->>Developer: Report TM010 for an eligible call
Developer->>PreferStaticMockSyntaxCodeFixProvider: Apply the code fix
PreferStaticMockSyntaxCodeFixProvider->>RoslynDocument: Replace call with T.Mock() and add using when needed
RoslynDocument->>Developer: Return updated source
Suggested reviewers: quattordici
Merge Risk: 
Minimal · up to 90c94
-
No identified issue currently blocks merging, subject to normal build and test checks.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passedFull details: Docstring Coverage
-
Explanation
Docstring coverage is 39.29% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 28 functions across 9 files. (2 skipped: 2 unsupported.)
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
Finishing Touches
-
Generate docstrings
-
- Commit to this branch
- Create a new PR
Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
A rabbit reads the syntax bright,
And hops from Of to Mock outright.
A using joins when out of scope,
While comments stay and tests give hope.
Fix-all runs; the lines align,
The rabbit nibbles, pleased to find.
Review: TM010 prefer
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f3283da975
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
[Medium impact] The PR appears safe to merge; the remaining comment-loss case is non-blocking. SummaryAdds
Reviews (2) · Last reviewed commit: "fix(mocks): address TM010 review finding..." · Reviewed by Greptile |
- Add TUnit.Mocks.Analyzers.CodeFixers to TUnit.CI.slnx and TUnit.Dev.slnx so the CI library build produces its Release output before `pack --no-build`. - Interface `var` locals: report only when every use of the local is type-insensitive (member access, non-generic argument, explicitly typed target, declared return). Writes, tuple deconstruction and inferred uses such as Task.FromResult(mock) now suppress the diagnostic. - Check every simple name in the file, not just the call site, before relying on adding a file-level `using TUnit.Mocks;`. - Keep comments from the removed `Mock.Of<...>` tokens. - Test stubs return a wrapper subclass for interfaces, matching the generator. Co-Authored-By: Claude <noreply@anthropic.com>
Review of #7307 (TM010 prefer
|
|
Thanks for the review. Here is what I did with each suggestion, as of 90c94f8:
Also in that commit:
|
Summary
Adds an analyzer and code fix to TUnit.Mocks that move single-type mock creation from
Mock.Of<T>()to the recommendedT.Mock()syntax.TUnit.Mocks.Analyzers): reportsMock.Of<T>()andMock.Of<T>(behavior)calls that have aT.Mock()/T.Mock(behavior)equivalent.TUnit.Mocks.Analyzers.CodeFixersproject: rewrites the call, keeps the type as written (qualified, generic or alias), keeps the behavior argument, drops a?annotation, and addsusing TUnit.Mocks;when the extension members aren't in scope. Fix All is supported.analyzers/dotnet/cs, next to the existing analyzer DLL. Verified withdotnet pack.DiagnosticIdsconsts. The fixer uses them, notRules, following [Bug]: MissingFieldException for Latest migration analyser in VS2026 #6157, and aRulesDecouplingVerifierIL test enforces this.writing-tests/mocking/index.md, including thedotnet formatcommand for migrating a whole project.The ID is TM010 because the source generator already reports TM008 and TM009. A comment in
DiagnosticIdsrecords this.When TM010 is not reported
The analyzer reports only where the fixed code still compiles. It follows the source generator's own rules for emitting
T.Mock():MockRepository.Of<T>(), multi-interfaceOf<T1, T2>(), theIDefaultValueProvideroverload, and overloads that take constructor arguments.Mock.T.Mock()).T.Mock()returns the generated wrapper type, notMock<T>. This covers a reassignedvarlocal (top-level statements included), implicitly typed arrays, lambda returns, tuples and generic type inference.using TUnit.Mocks;would make an existing imported name ambiguous (e.g. another library'sArg).Known limitation: if an overloaded method takes both
M(IFoo)andM(Mock<IFoo>), passing the interface wrapper can make the call ambiguous. This is rare and not detected.Test plan
tests/TUnit.Mocks.Analyzers.Tests: 83/83 pass on net10.0. The project now pins Roslyn 4.14, so the code fix tests compile the fixed code against real C# 14extensionblocks that stand in for the generated ones.Mock.Of<T>()for an interface, a closed generic interface and an abstract class, with fully qualified names and no using.dotnet format analyzers --diagnostics TM010 --severity inforewrote all 4 calls and added the using, and the result builds.tests/TUnit.Mocks.Testsbuilds with the new analyzer, with no AD0001 crashes.dotnet pack src/TUnit.Mockscontainsanalyzers/dotnet/cs/TUnit.Mocks.Analyzers.CodeFixers.dll.🤖 Generated with Claude Code
Summary by CodeRabbit
T.Mock()instead of supportedMock.Of<T>()calls in eligible C# 14+ projects.