diff --git a/README.md b/README.md index 98048ec8..3fd3fe2e 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,24 @@ FastMoq is a provider-first .NET testing framework for auto-mocking, dependency-aware construction, and test-focused object creation. In v4, it ships with a bundled `reflection` default and optional Moq or NSubstitute integrations when you need provider-specific arrange syntax. -## Start Here +FastMoq is test-framework agnostic and can be used from xUnit, NUnit, MSTest, or other .NET test frameworks. -- If you are evaluating the project for the first time, read `Why FastMoq` first, then `Packages`, then the documentation links below. -- If you want the documentation portal home page with package-specific guidance, start with [FastMoq Documentation Home](https://help.fastmoq.com/). +## Evaluate FastMoq + +If you are comparing FastMoq with direct mock-provider usage or deciding whether it fits your test stack, use this order: + +1. Read `Why FastMoq` below for the high-level value proposition. +2. Use [Feature Comparison](https://help.fastmoq.com/docs/feature-parity/README.html) for the detailed FastMoq vs direct-provider story. +3. Use [Provider Capabilities](https://help.fastmoq.com/docs/getting-started/provider-capabilities.html) when you need the exact provider boundary. +4. Use [Benchmarks](https://help.fastmoq.com/docs/benchmarks/README.html) when you want the current measured runtime-overhead comparison. +5. Use [Migration Guide](https://help.fastmoq.com/docs/migration/README.html) and [What's New Since 3.0.0](https://help.fastmoq.com/docs/whats-new/README.html) if you are coming from the `3.0.0` public line. +6. Use [Roadmap Notes](https://help.fastmoq.com/docs/roadmap/README.html) only for future public product direction, not current support claims. + +## Choose Your Starting Point + +- If you already know you want package-specific guidance, start with [FastMoq Documentation Home](https://help.fastmoq.com/). - If you want a first test that works under the default `reflection` provider, start with [Getting Started Guide](https://help.fastmoq.com/docs/getting-started/README.html). -- If you want tracked `.Setup(...)` syntax, read [Provider Selection Guide](https://help.fastmoq.com/docs/getting-started/provider-selection.html) before copying any Moq-fluent examples. -- If you are upgrading from the `3.0.0` line, start with [Migration Guide](https://help.fastmoq.com/docs/migration/README.html) and [What's New Since 3.0.0](https://help.fastmoq.com/docs/whats-new/README.html). +- If you want tracked provider-specific `.Setup(...)` syntax, read [Provider Selection Guide](https://help.fastmoq.com/docs/getting-started/provider-selection.html) before copying any Moq-fluent examples. - Front-door examples use a couple of different assertion styles. Match the assertion library your test project already uses and keep that style consistent within the project. - Authoring ladder for the current v4 line: 1. provider-neutral helper first, such as `GetOrCreateMock(...)`, `Verify(...)`, `VerifyNoOtherCalls(...)`, `VerifyLogged(...)`, `WhenHttpRequest(...)`, or `AddType(...)` @@ -38,10 +49,12 @@ FastMoq ships with a bundled `reflection` provider, so you can start without tak ### Works well when a suite needs to stay maintainable -FastMoq pays off most when tests have multiple constructor dependencies, recurring framework abstractions, or a need to keep provider choices flexible over time. It targets .NET 8, 9, and 10, is designed around xUnit, and includes the analyzer pack by default in `FastMoq` and `FastMoq.Core` so provider-first guidance shows up directly in the IDE. +FastMoq pays off most when tests have multiple constructor dependencies, recurring framework abstractions, or a need to keep provider choices flexible over time. It targets .NET 8, 9, and 10, works with the .NET test framework your suite already uses, and includes the analyzer pack by default in `FastMoq` and `FastMoq.Core` so provider-first guidance shows up directly in the IDE. ### FastMoq vs Direct Mock Provider Usage +The example below uses xUnit-style attributes and Moq arrange syntax for illustration. The point of comparison is the FastMoq harness shape, not a requirement to use xUnit or Moq for every test suite. + Using a mock provider directly: ```csharp diff --git a/docfx.json b/docfx.json index 6398a2d5..9e44b282 100644 --- a/docfx.json +++ b/docfx.json @@ -34,6 +34,7 @@ "api/**.yml", "FAQs.md", "docs/README.md", + "docs/ai/**.md", "docs/api/**.md", "docs/benchmarks/**.md", "docs/breaking-changes/**.md", diff --git a/docs/README.md b/docs/README.md index ab066f92..d270cada 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,6 +4,8 @@ Welcome to the FastMoq documentation home page. Use this site when you already k If you are evaluating the project itself and want the high-level value proposition first, start with the [GitHub repository home page](https://github.com/cwinland/FastMoq). +If you are coming from that repository overview and now want the usage-side guide set, use this page for package choices, testing guidance, migration detail, and capability-specific docs. + ## Package Overview FastMoq ships as an aggregate package plus focused helper packages so a test suite can stay broad or stay lightweight depending on what it needs. @@ -60,10 +62,19 @@ Perfect for developers new to FastMoq. Learn the basics and write your first tes - [Explicit constructor selection in tests](./getting-started/testing-guide.md#explicit-constructor-selection-in-tests) - [Web helper guidance for controller and request tests](./getting-started/testing-guide.md#controller-testing) - [Executable testing examples](./samples/testing-examples.md) +- [AI prompt templates for new tests, modernization, and migration](./ai/README.md) - Understanding the architecture - Common patterns and best practices - Troubleshooting guide +### πŸ€– [AI-Assisted Workflows](./ai/README.md) + +Reusable prompt templates and guardrails for AI-assisted migration, new test authoring, and modernization work. + +- Task-specific prompts for migration, new tests, and modernization +- Shared anti-hallucination rules for validating packages, providers, namespaces, and locally available APIs +- Repo-first doc guidance for current-branch work with hosted-doc fallback guidance + ### πŸ”„ [Migration Guide](./migration/README.md) Practical guidance for moving from the public `3.0.0` release toward the current `4.3.0` provider-first patterns. @@ -86,10 +97,10 @@ Use the docs-side API overview when you want example-first entry points and cura Comprehensive comparison of FastMoq with other popular mocking frameworks. -- Side-by-side feature comparison -- Migration guides from Moq and NSubstitute -- Links to runnable benchmarks when raw overhead comparisons matter -- When to choose FastMoq vs alternatives +- Grouped parity matrix across provider model, verification, setup, and framework-integration dimensions +- Complete side-by-side examples only where the comparison materially helps the reader +- Provider-dependent notes for scenarios that do not flatten cleanly into one portable abstraction +- When to choose FastMoq versus a direct provider workflow ### πŸ‘¨β€πŸ³ [Cookbook](./cookbook/README.md) @@ -119,9 +130,13 @@ Runnable BenchmarkDotNet coverage for current provider-first FastMoq flows. - Includes the exact run command and benchmark scope for this branch - Links to the latest checked-in short-run results summary -### πŸ—ΊοΈ [Roadmap Notes](./roadmap/README.md) +### πŸ›£οΈ [Roadmap Notes](./roadmap/README.md) + +Forward-looking product direction for upcoming releases, including current v5 cleanup and generator planning. -Current provider-first direction, active architectural work, and intentionally deferred items. +- Near-term provider-first and helper-surface direction +- v5 packaging and obsolete-surface cleanup +- Formal [generator roadmap and design](./roadmap/generator-roadmap.md) for planned code-generation work ### πŸ†• [What's New Since 3.0.0](./whats-new/README.md) @@ -155,6 +170,7 @@ Intentional v4 breaking changes, with migration notes for changed behavior. Direct routes: - Provider-first authoring: [Getting Started](./getting-started/README.md), [Testing Guide](./getting-started/testing-guide.md), and [API quick reference](./api/quick-reference.md) +- AI-assisted workflows: [AI Prompt Templates](./ai/README.md), [Testing Guide](./getting-started/testing-guide.md), and [Migration Guide](./migration/README.md) - Harness and wrapper decisions: [Choose The Narrowest Harness](./getting-started/testing-guide.md#choose-the-narrowest-harness) and [Local Wrapper Boundary](./getting-started/testing-guide.md#local-wrapper-boundary) - Migration cleanup: [Migration Guide](./migration/README.md), [Provider and compatibility guidance](./migration/provider-and-compatibility.md), and [API replacements and migration exceptions](./migration/api-replacements-and-exceptions.md) - Troubleshooting provider or package mismatches: [Provider selection](./getting-started/provider-selection.md), [Provider capabilities](./getting-started/provider-capabilities.md), and [Getting Started package choices](./getting-started/README.md#package-choices) diff --git a/docs/ai/README.md b/docs/ai/README.md new file mode 100644 index 00000000..a726e5ab --- /dev/null +++ b/docs/ai/README.md @@ -0,0 +1,199 @@ +# AI Prompt Templates For FastMoq + +Use the checked-in repo docs under `docs/` as the source of truth for current-branch work. + +This page collects reusable AI prompt templates for three common jobs: + +- migrating tests from FastMoq `3.0.0`-style usage to the current v4 line +- writing new tests directly against the current FastMoq APIs +- modernizing or reviewing existing tests that are already on v4-era packages + +The hosted `help.fastmoq.com` site is a useful published mirror, but it can lag the current branch. If you are working in a checked-out repo, keep the repo-relative doc paths in the prompt body. If you only have browser access, substitute the matching GitHub pages for those files. + +## When to use which prompt + +| Prompt | Use it when | Avoid it when | +| --- | --- | --- | +| Project-level migration prompt | You are migrating a suite in small batches and still need to decide which tests should stabilize first versus modernize now. | You want every touched file to remove obsolete APIs aggressively. | +| Strict obsolete-cleanup prompt | The suite is already stable and you want touched files fully converted away from obsolete FastMoq entry points wherever possible. | You are still in the earliest "just get the suite green" phase. | +| New test authoring prompt | You are writing a new FastMoq test and want the current preferred APIs instead of migration compatibility paths. | You are primarily rewriting existing legacy tests with minimal churn. | +| Existing test modernization prompt | The project is already on current packages and you want to improve clarity, provider-first usage, or helper choice without treating the work as a v3-to-v4 migration. | You are doing the first stabilization pass of a legacy migration. | + +## Shared rules for every prompt + +Use these rules in every prompt below. They exist to stop the model from inventing FastMoq APIs or suggesting helpers that are not actually available in the current project. + +- Before editing, inspect package references to confirm which FastMoq packages are installed, including provider packages such as `FastMoq.Provider.Moq` and `FastMoq.Provider.NSubstitute`, plus helper packages such as `FastMoq.Web`, `FastMoq.Database`, and `FastMoq.AzureFunctions`. +- Inspect `using` directives, `GlobalUsings.cs`, and nearby tests or shared helpers before assuming extension methods such as `Setup(...)`, `AsMoq()`, `AsNSubstitute()`, `VerifyLogged(...)`, `WhenHttpRequest(...)`, or typed service-provider helpers are available in the current project. +- Verify each FastMoq API you plan to introduce against the local codebase and the referenced docs before using it. +- If you cannot confirm that an API exists in the current project or docs, do not guess. Report the uncertainty, name what is missing, and use the nearest documented alternative instead. +- Prefer the narrowest current FastMoq API that matches the test intent. Do not rewrite to a broader or more compatibility-heavy surface unless the test still needs it. + +## Project-level migration prompt + +Use this prompt for staged migration work where package, provider, and obsolete-API decisions still matter. + +```text +I am migrating this test project from FastMoq 3.0.0-style usage to the current v4 provider-first APIs. + +Use these repo docs, in order, as the source of truth: +- docs/migration/README.md +- docs/migration/api-replacements-and-exceptions.md +- docs/migration/provider-and-compatibility.md +- docs/migration/framework-and-web-helpers.md +- docs/getting-started/provider-selection.md +- docs/getting-started/provider-capabilities.md +- docs/samples/testing-examples.md + +If only one doc can be provided, use docs/migration/README.md. +If only two docs can be provided, use docs/migration/README.md and docs/migration/api-replacements-and-exceptions.md. +If I am working from hosted docs instead of a repo checkout, use the matching GitHub pages for those files and treat the checked-in repo docs as authoritative for current-branch behavior. + +Before editing: +- inspect package references and determine whether the project uses the aggregate FastMoq package or split packages such as FastMoq.Core, FastMoq.Web, FastMoq.Database, FastMoq.Provider.Moq, or FastMoq.Provider.NSubstitute +- inspect using directives, global usings, shared helpers, and base classes before leaf tests, especially around `.Object`, `.Reset()`, `Func`, logger verification helpers, and framework service-provider setup such as `FunctionContext.InstanceServices` +- inspect nearby tests to confirm which FastMoq APIs are actually available in this project before proposing replacements +- identify Moq-specific dependencies such as GetMock(), direct Mock, Setup(...), SetupSet(...), SetupAllProperties(), Protected(), VerifyLogger(...), and out/ref verification +- identify NSubstitute-specific usage, web helpers, DbContext helpers, and HTTP compatibility helpers that imply package or provider boundaries + +Migration rules: +- prefer GetOrCreateMock(), GetObject(), Verify(...), VerifyNoOtherCalls(...), VerifyLogged(...), and TimesSpec when that makes the test clearer +- treat obsolete APIs such as GetMock(), VerifyLogger(...), Initialize(...), and MockOptional as migration targets, not the preferred end state +- replace GetMock() with GetOrCreateMock() plus provider-package extensions such as AsMoq() only when those extensions are confirmed to exist in the current project +- for Moq-specific setup on IFastMock, confirm the project references FastMoq.Provider.Moq and imports the needed provider extensions before using Setup(...), SetupGet(...), SetupSequence(...), or Protected() +- for NSubstitute migration, replace Moq Setup(...) syntax with native NSubstitute arrangement syntax only after confirming the project is actually using the NSubstitute provider +- for controller or HttpContext tests, prefer FastMoq.Web helpers such as CreateHttpContext(...), CreateControllerContext(...), SetupClaimsPrincipal(...), AddHttpContext(...), and AddHttpContextAccessor(...) only when FastMoq.Web is present +- if exact custom claims matter, use TestClaimsPrincipalOptions with IncludeDefaultIdentityClaims = false +- if local repo helpers overlap with FastMoq.Web helpers, re-point the local wrappers first and simplify later only if it improves clarity +- do not force provider-neutral rewrites where Moq compatibility is still the clearer path, but still remove obsolete entry points where a documented v4 replacement exists +- when a replacement is blocked, cite the concrete blocker such as a missing package, missing namespace import, provider capability difference, or a documented compatibility exception from the migration docs + +For this batch: +- explain the package and provider assumptions you found +- explain which tests should stay on Moq and which can move toward provider-neutral APIs +- convert obsolete APIs to their v4 replacements wherever the test intent stays clear and the replacement is confirmed locally +- make the smallest safe edits needed +- list any obsolete usages that remain and the exact blocker for each one +- if you cannot confirm a proposed FastMoq API, stop and say which symbol could not be validated instead of inventing a replacement +``` + +Use this version for incremental migration. Stabilize first if the suite is still red. Once it is stable, treat obsolete removal as the default for touched tests and leave compatibility APIs only where a real blocker remains. + +## Strict obsolete-cleanup prompt + +Use this version when the goal is to keep the suite passing and remove obsolete FastMoq entry points from every touched file unless a concrete blocker remains. + +```text +I am migrating this FastMoq test file to the current v4 APIs. + +Use these repo docs, in order, as the source of truth: +- docs/migration/README.md +- docs/migration/api-replacements-and-exceptions.md +- docs/migration/provider-and-compatibility.md +- docs/migration/framework-and-web-helpers.md +- docs/getting-started/provider-selection.md +- docs/getting-started/provider-capabilities.md + +If only one doc can be provided, use docs/migration/README.md. +If only two docs can be provided, use docs/migration/README.md and docs/migration/api-replacements-and-exceptions.md. +If I am working from hosted docs instead of a repo checkout, use the matching GitHub pages for those files and treat the checked-in repo docs as authoritative for current-branch behavior. + +Before editing: +- inspect package references, active provider assumptions, using directives, and nearby test patterns +- inspect shared helpers or base classes first if the file depends on them +- identify every use of GetMock(), VerifyLogger(...), Initialize(...), MockOptional, and other obsolete or compatibility-only FastMoq APIs in this file +- confirm that each planned replacement API exists in the current project and referenced docs before using it +- identify any Moq-only or NSubstitute-only behavior that still requires provider-specific handling + +Editing rules: +- replace obsolete FastMoq APIs with current documented v4 equivalents wherever possible +- prefer GetOrCreateMock(), GetObject(), Verify(...), VerifyNoOtherCalls(...), VerifyLogged(...), TimesSpec, AddType(...), and FastMoq-owned helper packages when appropriate and confirmed locally +- use GetOrCreateMock().AsMoq() or direct provider-package extensions instead of leaving GetMock() behind when the test still needs Moq semantics and the provider package is present +- only keep an obsolete call if the file still depends on a compatibility-only shape with no clean documented v4 replacement in that test +- if a replacement API cannot be confirmed in the current project or docs, stop and report the gap instead of guessing + +Output expectations: +- make the smallest safe edits needed +- list every obsolete usage that was replaced +- list every obsolete usage that remains and explain the specific blocker for each one +``` + +Use the strict variant after the first stabilization pass. It is for touched-file cleanup, not the earliest "just get the suite green" phase. + +## New test authoring prompt + +Use this prompt when you are writing a new FastMoq test and want the current preferred APIs from the start instead of migration compatibility paths. + +```text +I am writing a new test that should use the current FastMoq APIs and patterns. + +Use these repo docs, in order, as the source of truth: +- docs/getting-started/testing-guide.md +- docs/getting-started/provider-selection.md +- docs/getting-started/provider-capabilities.md +- docs/samples/testing-examples.md +- docs/cookbook/README.md +- docs/migration/api-replacements-and-exceptions.md only if a compatibility or legacy question comes up + +If only one doc can be provided, use docs/getting-started/testing-guide.md. +If only two docs can be provided, use docs/getting-started/testing-guide.md and docs/samples/testing-examples.md. +If I am working from hosted docs instead of a repo checkout, use the matching GitHub pages for those files and treat the checked-in repo docs as authoritative for current-branch behavior. + +Before writing the test: +- inspect package references, provider selection, using directives, and nearby tests to confirm the available FastMoq APIs in this project +- inspect the component or service under test and choose the narrowest harness that matches the behavior under test +- confirm whether this test should use direct construction, direct Mocker usage, MockerTestBase, FastMoq.Web helpers, DbContext helpers, or typed service-provider helpers +- confirm whether the arrange side should stay provider-specific for the selected provider or whether the test can stay fully provider-neutral + +Authoring rules: +- prefer current provider-first APIs such as GetOrCreateMock(), GetObject(), Verify(...), VerifyNoOtherCalls(...), VerifyLogged(...), TimesSpec, AddType(...), CreateStandaloneFastMock(), and FastMoq-owned helpers when they fit the test intent +- do not introduce obsolete or compatibility-only APIs such as GetMock(), VerifyLogger(...), Initialize(...), MockOptional, or Strict unless the test is explicitly documenting a compatibility scenario +- if provider-specific setup is needed, use the provider-specific syntax that matches the confirmed provider and package references +- prefer repo-backed example patterns from docs/samples/testing-examples.md and nearby tests over invented helper shapes +- if you cannot confirm that a FastMoq API exists in this project or docs, stop and say what could not be validated instead of inventing a symbol + +For the response: +- explain the harness and provider choice briefly +- write the smallest clear test that matches current FastMoq guidance +- call out any package or import required for the APIs you used +``` + +Use this version for new code, examples, and fresh tests in already-upgraded projects. + +## Existing test modernization prompt + +Use this prompt when a test already runs on current packages but you want to improve clarity, reduce compatibility carryover, or move toward clearer provider-first patterns without treating the work as a full migration. + +```text +I am modernizing an existing FastMoq test that already runs on current packages. The goal is clearer current-style FastMoq usage, not a broad migration rewrite. + +Use these repo docs, in order, as the source of truth: +- docs/getting-started/testing-guide.md +- docs/samples/testing-examples.md +- docs/getting-started/provider-capabilities.md +- docs/migration/api-replacements-and-exceptions.md when compatibility carryover or obsolete APIs appear +- docs/migration/framework-and-web-helpers.md when the churn is in FastMoq.Web, service-provider helpers, or framework-specific helpers + +If only one doc can be provided, use docs/getting-started/testing-guide.md. +If only two docs can be provided, use docs/getting-started/testing-guide.md and docs/samples/testing-examples.md. +If I am working from hosted docs instead of a repo checkout, use the matching GitHub pages for those files and treat the checked-in repo docs as authoritative for current-branch behavior. + +Before editing: +- inspect package references, using directives, nearby tests, and shared helpers to confirm the current FastMoq surface in this project +- identify whether the test is carrying forward compatibility-only patterns, overly broad harness choices, provider-specific verification that could be provider-first, or helper indirection that no longer adds value +- confirm which replacement APIs are both documented and locally available before suggesting them + +Modernization rules: +- prefer clearer current APIs when the rewrite is mechanical and low risk +- keep provider-specific setup only where the test still depends on provider-specific semantics +- prefer Mocker.Verify(...), VerifyNoOtherCalls(...), VerifyLogged(...), TimesSpec, GetObject(), AddType(...), and FastMoq-owned helpers where they make the intent clearer +- do not expand local wrapper layers that only forward to verification APIs +- if a proposed cleanup depends on an API that cannot be confirmed in the local project or docs, report the gap instead of guessing + +For the response: +- explain the modernization choices briefly +- make the smallest safe clarity improvements +- list any compatibility-heavy patterns that remain and why they were kept +``` + +Use this version for cleanup passes, authoring reviews, and small refactors in already-upgraded test suites. diff --git a/docs/cookbook/README.md b/docs/cookbook/README.md index d259977d..dc012636 100644 --- a/docs/cookbook/README.md +++ b/docs/cookbook/README.md @@ -71,6 +71,8 @@ public class UsersController : ControllerBase #### Test Example +The cookbook snippets often use xUnit attributes as one example of test-framework syntax, but the FastMoq APIs in these examples are not tied to xUnit. Keep the FastMoq calls and swap in the test framework syntax your project already uses. + ```csharp using FastMoq; using AwesomeAssertions; diff --git a/docs/feature-parity/README.md b/docs/feature-parity/README.md index a936f262..ccc8d57b 100644 --- a/docs/feature-parity/README.md +++ b/docs/feature-parity/README.md @@ -1,67 +1,164 @@ -# FastMoq Feature Parity & Comparison +# FastMoq Feature Parity & Framework Comparison -This page is for comparison, not step-by-step setup. Use it to see where FastMoq removes boilerplate compared with using a mock provider directly, then follow the focused guides for implementation details. +This page is a comparison aid, not a setup guide. Use it to evaluate where FastMoq changes the authoring model compared with using a mocking framework directly, then follow the focused guides when you are ready to implement a specific test shape. + +FastMoq is not trying to erase every provider-specific behavior. Its main value is a provider-first layer for object creation, dependency injection, verification, and framework-heavy test helpers so tests spend less effort on repeated wiring and more effort on behavior. + +## How To Read This Page + +Legend: + +- `βœ…`: built-in and documented as a first-class path in the framework being compared. +- `🟑`: supported, but with important constraints such as provider dependence, manual setup, or lack of one unified abstraction. +- `❌`: not supported as a built-in capability in the compared scope. + +Reading notes: + +- For FastMoq, `🟑` often means the capability is still available through the selected provider, but FastMoq does not pretend it is fully portable across every provider. +- For direct providers, `🟑` is reserved for native-framework capabilities that are genuinely present but come with notable constraints. +- The direct-provider columns score the native framework itself, not third-party add-on packages that layer auto-mocking, DI-aware construction, or extra framework helpers on top of that provider. +- FakeItEasy appears here only as an external direct-framework baseline. The current FastMoq repo does not ship a FastMoq provider for FakeItEasy, so this page does not show FastMoq-plus-FakeItEasy implementation examples. ## Framework Comparison Overview -| Framework | Auto-Injection | Fluent Setup | DbContext Support | Web Testing | Learning Curve | -| --- | --- | --- | --- | --- | --- | -| **FastMoq** | βœ… Full | βœ… Yes | βœ… Built-in | βœ… Blazor/MVC | 🟒 Easy | -| **Moq** | ❌ Manual | βœ… Yes | 🟑 Manual | 🟑 Manual | 🟑 Medium | -| **NSubstitute** | ❌ Manual | βœ… Yes | 🟑 Manual | 🟑 Manual | 🟒 Easy | -| **FakeItEasy** | ❌ Manual | βœ… Yes | 🟑 Manual | 🟑 Manual | 🟒 Easy | +### Construction And Authoring Model + +| Capability | FastMoq | Moq | NSubstitute | FakeItEasy | +| --- | --- | --- | --- | --- | +| Multiple provider backends behind one test API | βœ… | ❌ | ❌ | ❌ | +| Explicit provider selection and scoped overrides | βœ… | ❌ | ❌ | ❌ | +| Automatic dependency graph construction | βœ… | ❌ | ❌ | ❌ | +| DI-aware component creation | βœ… | ❌ | ❌ | ❌ | +| Constructor guard helpers | βœ… | ❌ | ❌ | ❌ | +| Method parameter auto-injection | βœ… | ❌ | ❌ | ❌ | +| Native framework setup syntax | 🟑 (1) | βœ… | βœ… | βœ… | +| Portable argument-matching surface | βœ… | ❌ | ❌ | ❌ | + +Construction notes: + +- `(1)` for FastMoq means the test can still use native provider setup syntax, but that setup remains provider-specific rather than fully portable across every FastMoq provider. + +### Verification, Framework Integration, And Tooling -## Detailed Feature Comparison +| Capability | FastMoq | Moq | NSubstitute | FakeItEasy | +| --- | --- | --- | --- | --- | +| Portable verification surface across providers | βœ… | ❌ | ❌ | ❌ | +| Native framework verification syntax | 🟑 (2) | βœ… | βœ… | βœ… | +| Async arrangement for `Task`-returning members | βœ… | βœ… | βœ… | βœ… | +| Exception arrangement | 🟑 (3) | βœ… | βœ… | βœ… | +| DbContext-oriented helper layer | βœ… | ❌ | ❌ | ❌ | +| Typed `IServiceProvider` and scope helper layer | βœ… | ❌ | ❌ | ❌ | +| `HttpClient` request helper layer | βœ… | ❌ | ❌ | ❌ | +| ASP.NET Core controller and HttpContext helper layer | βœ… | ❌ | ❌ | ❌ | +| Blazor and bUnit integration helper layer | βœ… | ❌ | ❌ | ❌ | +| Azure SDK credential, pageable, and client-registration helper layer | βœ… | ❌ | ❌ | ❌ | +| Azure Functions worker and HTTP-trigger helper layer | βœ… | ❌ | ❌ | ❌ | +| Analyzer-guided modernization in this repo | βœ… | ❌ | ❌ | ❌ | -### 1. Mock Creation and Management +Verification and integration notes: -#### FastMoq Mock Creation +- `(2)` for FastMoq verification syntax means provider-native verification APIs can still be used when a test intentionally stays provider-specific, but FastMoq's primary first-party path is the provider-neutral `Verify(...)` and `VerifyNoOtherCalls(...)` surface, plus `VerifyLogged(...)` when the selected provider supports logger capture. +- `(3)` for FastMoq exception arrangement means the behavior is available, but the arrange step may still rely on the selected provider's native exception setup syntax rather than one shared FastMoq helper. + +## What The Matrix Means In Practice + +The table is intentionally focused on current validated capability coverage, not on future wish lists. + +- FastMoq is strongest where test construction, provider-neutral verification, framework helpers, and migration tooling matter more than using raw provider syntax everywhere. +- Direct providers remain strong when a suite intentionally stays native to one framework and the team is comfortable owning constructor wiring, registration setup, and provider-specific helper code directly in the tests. +- If a workflow becomes possible only after adding ecosystem packages around a provider, that is outside the scope of these direct-framework cells and should be documented as a separate package-stack comparison instead. +- That means rows explicitly described as a helper layer stay `❌` for direct providers unless the provider itself ships that helper surface natively. +- Core helper rows include FastMoq's typed `IServiceProvider` and scope helpers plus the `WhenHttpRequest(...)` and `WhenHttpRequestJson(...)` helper flow for outbound HTTP behavior. In FastMoq, that `HttpClient` helper path stays provider-neutral. +- Azure-specific rows refer to the documented first-party FastMoq packages `FastMoq.Azure` and `FastMoq.AzureFunctions`, including helpers for credentials, pageable builders, Azure-oriented DI, client registration, `FunctionContext.InstanceServices`, and HTTP-trigger request or response objects. +- Some advanced areas remain intentionally provider-dependent today, especially when the semantics are tightly coupled to one provider's model. Those scenarios are better explained in focused notes than flattened into misleading chart cells. + +## Detailed Comparisons + +### 1. Object Graph Wiring And Everyday Setup + +This is the most common FastMoq value proposition: the component is created for you, tracked dependencies live in one registry, and the assert side can stay provider-neutral even when the arrange side uses provider-native syntax. + +#### FastMoq Example + +This example uses the FastMoq harness with Moq-provider setup syntax, so it assumes the Moq provider extensions are available. ```csharp -public class ServiceTests : MockerTestBase +public class OrderServiceTests : MockerTestBase { [Fact] - public void Test_AutomaticMocks() + public async Task ProcessOrderAsync_ShouldSaveOrder_WhenPaymentSucceeds() { - Component.SomeMethod(); + Mocks.GetOrCreateMock() + .Setup(x => x.ProcessPayment(100m)) + .ReturnsAsync(true); + + var result = await Component.ProcessOrderAsync(100m); - Mocks.Verify(x => x.Method(), TimesSpec.Once); + result.Should().BeTrue(); + Mocks.Verify(x => x.SaveOrder(100m), TimesSpec.Once); + Mocks.Verify(x => x.SendReceipt(100m), TimesSpec.Once); } } ``` -#### Direct Provider Mock Creation +#### Direct Moq Example ```csharp -public class ServiceTests +public class OrderServiceTests { - private readonly Mock _dependency1Mock; - private readonly Mock _dependency2Mock; - private readonly Mock> _loggerMock; - private readonly MyService _service; + private readonly Mock _paymentServiceMock = new(); + private readonly Mock _orderRepositoryMock = new(); + private readonly Mock _emailServiceMock = new(); + private readonly Mock> _loggerMock = new(); + private readonly OrderService _service; - public ServiceTests() + public OrderServiceTests() { - _dependency1Mock = new Mock(); - _dependency2Mock = new Mock(); - _loggerMock = new Mock>(); - _service = new MyService(_dependency1Mock.Object, _dependency2Mock.Object, _loggerMock.Object); + _service = new OrderService( + _paymentServiceMock.Object, + _orderRepositoryMock.Object, + _loggerMock.Object, + _emailServiceMock.Object); } [Fact] - public void Test_ManualMocks() + public async Task ProcessOrderAsync_ShouldSaveOrder_WhenPaymentSucceeds() { - _service.SomeMethod(); - _dependency1Mock.Verify(x => x.Method(), Times.Once); + _paymentServiceMock + .Setup(x => x.ProcessPayment(100m)) + .ReturnsAsync(true); + + var result = await _service.ProcessOrderAsync(100m); + + result.Should().BeTrue(); + _orderRepositoryMock.Verify(x => x.SaveOrder(100m), Times.Once); + _emailServiceMock.Verify(x => x.SendReceipt(100m), Times.Once); } } ``` -FastMoq removes most constructor wiring and repeated mock declarations from the test class. +The test goal is the same in both versions. The difference is where the ceremony lives: direct provider usage spells out every collaborator and subject-construction step, while FastMoq keeps the object graph inside the harness and lets the test focus on the behavior under assertion. + +Provider note: + +- When the selected provider is NSubstitute, keep the same component creation and provider-neutral verify calls, then translate the arrange step into native substitute syntax: + +```csharp +using var providerScope = MockingProviderRegistry.Push("nsubstitute"); + +Mocks.GetOrCreateMock() + .AsNSubstitute() + .ProcessPayment(100m) + .Returns(Task.FromResult(true)); +``` + +That is the main provider-specific rule on this page: FastMoq can unify the test harness and verify layer, but native arrange syntax still follows the selected provider when the test depends on provider-specific setup APIs. + +### 2. Constructor And Guard Testing -### 2. Constructor Parameter Testing +FastMoq has first-party helpers for constructor guard coverage. Direct provider usage can still test the same behavior, but it usually turns into one test per parameter or one hand-written helper per constructor shape. -#### FastMoq Constructor Testing +#### FastMoq Guard Helper ```csharp [Fact] @@ -72,7 +169,7 @@ public void Constructor_ShouldValidateParameters() } ``` -#### Direct Provider Constructor Testing +#### Direct Provider Guard Tests ```csharp [Fact] @@ -90,11 +187,13 @@ public void Constructor_ShouldThrowWhenDependency2IsNull() } ``` -FastMoq turns repeated guard-clause tests into one helper-driven assertion path. +The direct-provider path is not wrong. It is just repetitive. FastMoq turns repeated guard-clause coverage into one helper-driven test path that follows the same constructor-selection logic as the rest of the harness. + +### 3. DbContext Workflows -### 3. DbContext Mocking +DbContext testing is where the difference between a helper layer and a direct provider becomes easy to see. FastMoq keeps the DbContext in the same tracked registry as the rest of the test doubles. Direct provider usage usually means building a mock DbContext plus every `DbSet` behavior the query needs. -#### FastMoq DbContext Testing +#### FastMoq DbContext Path ```csharp public class BlogServiceTests : MockerTestBase @@ -117,38 +216,41 @@ public class BlogServiceTests : MockerTestBase } ``` -#### Direct Provider DbContext Testing +#### Direct Moq DbContext Path ```csharp -public class BlogServiceTests +[Fact] +public void GetBlog_ShouldReturnBlog() { - private readonly Mock _contextMock; - private readonly Mock> _blogSetMock; - private readonly BlogService _service; - - public BlogServiceTests() + var blogs = new List { - var blogs = new List { new Blog { Id = 1, Title = "Test" } }.AsQueryable(); + new() { Id = 1, Title = "Test" }, + }.AsQueryable(); - _blogSetMock = new Mock>(); - _blogSetMock.As>().Setup(m => m.Provider).Returns(blogs.Provider); - _blogSetMock.As>().Setup(m => m.Expression).Returns(blogs.Expression); - _blogSetMock.As>().Setup(m => m.ElementType).Returns(blogs.ElementType); - _blogSetMock.As>().Setup(m => m.GetEnumerator()).Returns(blogs.GetEnumerator()); + var blogSetMock = new Mock>(); + blogSetMock.As>().Setup(x => x.Provider).Returns(blogs.Provider); + blogSetMock.As>().Setup(x => x.Expression).Returns(blogs.Expression); + blogSetMock.As>().Setup(x => x.ElementType).Returns(blogs.ElementType); + blogSetMock.As>().Setup(x => x.GetEnumerator()).Returns(blogs.GetEnumerator()); - _contextMock = new Mock(); - _contextMock.Setup(c => c.Blogs).Returns(_blogSetMock.Object); + var contextMock = new Mock(); + contextMock.Setup(x => x.Blogs).Returns(blogSetMock.Object); - _service = new BlogService(_contextMock.Object); - } + var service = new BlogService(contextMock.Object); + + var result = service.GetBlog(1); + + result.Should().NotBeNull(); } ``` -FastMoq keeps DbContext setup inside the same mock registry and lifecycle as the rest of the test. +The direct-provider example is complete on purpose because this is one of the places where incomplete comparison snippets are misleading. The point is not that direct providers cannot test `DbContext`. They can. The point is that FastMoq gives that workflow a first-party path inside the same mock registry as the rest of the test. + +### 4. Web And Blazor Testing -### 4. Web and Blazor Testing +FastMoq does not replace bUnit or ASP.NET test primitives. It layers tracked mocks and web-focused helpers on top of them. -#### FastMoq Blazor Testing +#### FastMoq Blazor Path ```csharp public class CounterComponentTests : MockerBlazorTestBase @@ -163,7 +265,7 @@ public class CounterComponentTests : MockerBlazorTestBase } ``` -#### Direct Provider Blazor Testing +#### Direct Provider Blazor Path ```csharp public class CounterComponentTests : BunitContext @@ -180,13 +282,13 @@ public class CounterComponentTests : BunitContext } ``` -FastMoq adds mock registry support on top of the normal Blazor component test workflow. +For a simple component interaction, both paths are straightforward. The FastMoq-specific value shows up when the same test also needs tracked collaborators, typed `IServiceProvider` helpers, `HttpContext`, claims, or other web helpers that would otherwise be stitched together manually around the component test. ### 5. Method Parameter Auto-Injection -`CallMethod(...)` is useful when the method under test takes several collaborators as parameters instead of only constructor dependencies. If you supply the business argument that matters to the test, FastMoq can fill the omitted parameters when they are mocks or other types FastMoq can resolve through its normal creation pipeline. +`CallMethod(...)` matters when the method under test takes several collaborators as parameters instead of only constructor dependencies. FastMoq can fill omitted mockable parameters while still letting the test override the business argument that matters. -#### FastMoq Method Invocation +#### FastMoq CallMethod Path ```csharp [Fact] @@ -198,7 +300,7 @@ public void ProcessData_ShouldReturnData_WhenCollaboratorsAreAutoInjected() } ``` -#### Direct Provider Method Invocation +#### Direct Provider Call Path ```csharp [Fact] @@ -214,71 +316,35 @@ public void ProcessData_ShouldReturnData() } ``` -FastMoq can fill the rest of the method signature automatically when the omitted parameters are mocks or mockable dependencies, while still letting you override the parameters that matter to the test. - -## Code Reduction Snapshot - -FastMoq is strongest when you want less test code spent on constructor wiring, dependency registration, and repeated setup. Direct provider usage stays viable, but it usually pushes more object graph assembly into each test class. - -### FastMoq Example - -```csharp -public class OrderServiceTests : MockerTestBase -{ - [Fact] - public async Task ProcessOrder_ShouldCompleteOrder() - { - Mocks.GetOrCreateMock() - .Setup(x => x.ProcessPayment(It.IsAny())) - .ReturnsAsync(true); - - var result = await Component.ProcessOrderAsync(100m); - - result.Should().BeTrue(); - } -} -``` +This is not a universal testing need, but when it shows up it is one of the more distinctive FastMoq capabilities because the harness can reuse the same resolution pipeline for method parameters that it already uses for constructor injection. -### Direct Provider Example +## What Still Stays Provider-Dependent -```csharp -public class OrderServiceTests -{ - private readonly Mock _paymentServiceMock; - private readonly Mock _orderRepositoryMock; - private readonly Mock> _loggerMock; - private readonly Mock _emailServiceMock; - private readonly OrderService _orderService; +Some capabilities are intentionally not flattened into one FastMoq abstraction today. - public OrderServiceTests() - { - _paymentServiceMock = new Mock(); - _orderRepositoryMock = new Mock(); - _loggerMock = new Mock>(); - _emailServiceMock = new Mock(); +- Protected-member interception, call-base behavior, and similar class-mocking semantics still depend on the selected provider. +- Ordered-call, sequence-heavy, or event-centric scenarios are often clearer when documented in provider-native terms instead of forcing them into a single portable surface. +- Exception arrangement can still require native provider syntax even when the component creation and verification layers stay on FastMoq. - _orderService = new OrderService( - _paymentServiceMock.Object, - _orderRepositoryMock.Object, - _loggerMock.Object, - _emailServiceMock.Object); - } -} -``` +That is why the matrix uses `🟑` in a few places where a direct provider would say `βœ…`. The capability may still be available in a FastMoq-based suite, but the suite reaches it through the selected provider rather than through one provider-neutral helper. -The main value is not a special assertion syntax. It is keeping the test focused on behavior instead of mock construction and repeated dependency plumbing. +For follow-up guidance on these provider-dependent gaps, see [Provider Capabilities](../getting-started/provider-capabilities.md) and the roadmap notes in [Roadmap](../roadmap/README.md). -## FastMoq-Specific Capabilities +## Why Teams Still Choose FastMoq -- Built-in known-type mappings for common framework abstractions. -- Constructor guard testing helpers. -- `CallMethod(...)` auto-parameter resolution. -- Blazor test base integration. -- `ScenarioBuilder` support that still works across providers because verification stays provider-neutral. +- The harness can create the subject under test and track the dependency graph automatically. +- Verification can stay provider-neutral even when setup remains provider-specific. +- DbContext, Blazor, `HttpContext`, typed `IServiceProvider`, and other framework-heavy scenarios can stay inside the same FastMoq test surface. +- Outbound `HttpClient` behavior can stay on the provider-neutral `WhenHttpRequest(...)` and `WhenHttpRequestJson(...)` helper path instead of dropping directly into provider-specific handler interception for every test. +- Azure SDK and Azure Functions test helpers can stay inside the same FastMoq package family instead of requiring a separate local helper stack. +- Analyzer guidance helps modernize older suites toward current provider-first usage instead of leaving every team to rediscover the same migration decisions. ## Where To Go Next - [Getting Started](../getting-started/README.md) +- [Provider Selection](../getting-started/provider-selection.md) +- [Provider Capabilities](../getting-started/provider-capabilities.md) - [Testing Guide](../getting-started/testing-guide.md) - [Migration Guide](../migration/README.md) +- [Roadmap](../roadmap/README.md) - [Samples](../samples/README.md) diff --git a/docs/getting-started/README.md b/docs/getting-started/README.md index de26fb5a..2ee951b9 100644 --- a/docs/getting-started/README.md +++ b/docs/getting-started/README.md @@ -60,6 +60,8 @@ For the repo-native testing conventions and framework-specific guidance used by When you are deciding whether a test should stay plain, use direct `Mocker` usage, or move into a shared harness or wrapper layer, start with [Choose The Narrowest Harness](./testing-guide.md#choose-the-narrowest-harness) and [Local Wrapper Boundary](./testing-guide.md#local-wrapper-boundary). +If you want reusable AI workflows for new tests, modernization, or migration work instead of writing prompts from scratch, see [AI Prompt Templates](../ai/README.md). + If you want examples that run directly in this repository instead of static snippets only, see [Executable Testing Examples](../samples/testing-examples.md). If you are updating older FastMoq usage from the last public `3.0.0` release, see [Migration Guide: 3.0.0 To The Current v4 Line](../migration/README.md). @@ -226,7 +228,7 @@ using FastMoq.Extensions; // Core helper extensions such as VerifyLogged(...), A using Microsoft.Extensions.Logging; // ILogger or LogLevel in your test or component using AwesomeAssertions; // If you use AwesomeAssertions in your assertions using Shouldly; // If your project uses Shouldly instead -using Xunit; // Or the test framework of your choice +using Xunit; // Example only; replace with the test framework namespace your project uses ``` `Mocker` and `MockerTestBase` live in `FastMoq`. @@ -270,6 +272,8 @@ Azure Functions also exposes non-extension builder helpers in `FastMoq.AzureFunc Let's create a simple service and write a test for it using FastMoq. +The snippets below use xUnit attributes only as one example of test-framework syntax. The FastMoq APIs shown here are not tied to xUnit, so keep the FastMoq calls and use the test framework your project already standardizes on. + ### 1. Create a Service to Test First, let's create a simple file processing service that depends on the `IFileSystem` interface: diff --git a/docs/getting-started/provider-selection.md b/docs/getting-started/provider-selection.md index 48e2a3e2..b4ded4d3 100644 --- a/docs/getting-started/provider-selection.md +++ b/docs/getting-started/provider-selection.md @@ -157,9 +157,11 @@ Analyzer note: The examples below are alternatives to the assembly attributes. Use them when registration and selection need to happen together before the suite creates `Mocker` instances, but the decision cannot be expressed with `FastMoqDefaultProvider(...)` or `FastMoqRegisterProvider(...)`. +Choose the startup hook that matches your test framework. These are parallel framework-specific examples, not different FastMoq product modes. + ### xUnit -If you need startup code in xUnit, a module initializer is a portable option that works well for provider registration and default-provider selection. Consumers on xUnit v3 may also choose assembly fixtures or test pipeline startup when those fit their broader test-bootstrap model. +For xUnit suites, a module initializer is one portable option for provider registration and default-provider selection. Consumers on xUnit v3 may also choose assembly fixtures or test pipeline startup when those fit their broader test-bootstrap model. ```csharp using System.Runtime.CompilerServices; @@ -484,7 +486,7 @@ The repo now includes an executable provider-selection example in: - `FastMoq.TestingExample/ProviderSelectionBootstrap.cs` - `FastMoq.TestingExample/ProviderSelectionExampleTests.cs` -That example declares Moq as the app-wide default for the example test assembly and then uses the Moq compatibility surface in a real xUnit test. +That example declares Moq as the app-wide default for the example test assembly and then uses the Moq compatibility surface in a test that happens to use xUnit syntax. ## When to choose which provider in v4 diff --git a/docs/getting-started/testing-guide.md b/docs/getting-started/testing-guide.md index 54b9c41c..aef49399 100644 --- a/docs/getting-started/testing-guide.md +++ b/docs/getting-started/testing-guide.md @@ -2,6 +2,8 @@ This guide documents the testing patterns that match FastMoq's current behavior in this repository. It is intentionally practical: use it when you need to decide which FastMoq API to reach for in a real test. +If you want reusable AI workflows for new tests, modernization, or migration work instead of writing prompts from scratch, see [AI Prompt Templates](../ai/README.md). + ## Start Here Use these rules first: diff --git a/docs/migration/README.md b/docs/migration/README.md index 1c7d0a52..3077bb67 100644 --- a/docs/migration/README.md +++ b/docs/migration/README.md @@ -6,7 +6,7 @@ It stays focused on migration boundaries, reading order, package and provider de ## Start here for migration -If you are using Copilot or another AI assistant for migration work, start with [Copilot migration prompts](./copilot-prompts.md). +If you are using Copilot or another AI assistant for migration work, start with [AI prompt templates](../ai/README.md). Use the prompt page as the operational entry point. Use this guide and the linked detail pages as the canonical migration rules. @@ -29,7 +29,7 @@ Quick routing: - If the churn is in controller helpers, principals, `HttpContext`, `IHttpContextAccessor`, keyed DI, or framework service-provider shims, go to [Framework and web helper migration](./framework-and-web-helpers.md). - If the churn is in constructor-check output plumbing or other test-framework-specific helper output paths, go to [API replacements and migration exceptions](./api-replacements-and-exceptions.md) and [Framework and web helper migration](./framework-and-web-helpers.md). - If you are replacing a specific API such as `Initialize(...)`, `VerifyLogger(...)`, `Strict`, `MockOptional`, `GetMock()`, `GetRequiredMock()`, or `CreateDetachedMock()`, go to [API replacements and migration exceptions](./api-replacements-and-exceptions.md). -- If you want a reusable AI workflow instead of writing prompts from scratch, go to [Copilot migration prompts](./copilot-prompts.md). +- If you want a reusable AI workflow instead of writing prompts from scratch, go to [AI prompt templates](../ai/README.md). ## Scope @@ -277,7 +277,7 @@ Open these only when you hit the relevant problem. That keeps this page short wi - [bUnit and Blazor test migration](./bunit-and-blazor-testing.md): package-level and helper-level migration guidance for `FastMoq.Web`, `MockerBlazorTestBase`, `RenderParameter`, nested rendered-component helpers, authorization wrappers, and navigation assertions. - [Framework and web helper migration](./framework-and-web-helpers.md): shared-helper rewrites, keyed DI, Azure Functions `InstanceServices`, `FastMoq.Web` helper usage, principals, and controller-context migration. - [API replacements and migration exceptions](./api-replacements-and-exceptions.md): old-to-new API guidance for `Initialize(...)`, HTTP helpers, `VerifyLogger(...)`, `TimesSpec`, `Strict`, `GetMock()`, `GetRequiredMock()`, legacy mock-creation helpers, `AddType(...)`, `DbContext`, `MockOptional`, provider-first access, and expected raw-Moq pockets. -- [Copilot migration prompts](./copilot-prompts.md): reusable prompt entry points for staged migration and stricter obsolete-surface cleanup. +- [AI prompt templates](../ai/README.md): reusable prompt entry points for migration, new-test authoring, and modernization workflows. ## Recommended migration order diff --git a/docs/migration/copilot-prompts.md b/docs/migration/copilot-prompts.md deleted file mode 100644 index a8833497..00000000 --- a/docs/migration/copilot-prompts.md +++ /dev/null @@ -1,93 +0,0 @@ -# Copilot Migration Prompts - -Use [Migration Guide: 3.0.0 To The Current v4 Line](./README.md) and its linked detail pages as the source of truth. - -This page only collects reusable AI prompt templates that point back to those migration docs. If you copy one of these prompts into a custom prompt, keep the doc links in the prompt body; the model does not need this page at runtime. - -## When to use which prompt - -| Prompt | Use it when | Avoid it when | -| --- | --- | --- | -| Project-level migration prompt | You are migrating a suite in small batches and still need to decide which tests should stabilize first versus modernize now. | You want every touched file to remove obsolete APIs aggressively. | -| Strict obsolete-cleanup prompt | The suite is already stable and you want touched files fully converted away from obsolete FastMoq entry points wherever possible. | You are still in the earliest "just get the suite green" phase. | - -## Project-level migration prompt - -Use this prompt for staged migration work where package, provider, and obsolete-API decisions still matter. - -```text -I am migrating this test project from FastMoq 3.0.0-style usage to the current v4 provider-first APIs. - -Use these docs, in order, as the source of truth: -- Main migration guide and routing: https://github.com/cwinland/FastMoq/blob/master/docs/migration/README.md -- API replacements and migration exceptions: https://github.com/cwinland/FastMoq/blob/master/docs/migration/api-replacements-and-exceptions.md -- Provider bootstrap, package boundaries, and Moq-to-NSubstitute translation: https://github.com/cwinland/FastMoq/blob/master/docs/migration/provider-and-compatibility.md -- Framework helpers, FastMoq.Web migration, claims-principal guidance, keyed DI, and FunctionContext.InstanceServices: https://github.com/cwinland/FastMoq/blob/master/docs/migration/framework-and-web-helpers.md - -If only one doc can be provided, use the main migration guide. If two can be provided, use the main migration guide and API replacements doc. - -Work only on a small batch of tests at a time and run tests frequently after each batch. - -Before editing: -- inspect package references and determine whether the project uses the aggregate FastMoq package or split packages such as FastMoq.Core, FastMoq.Web, FastMoq.Database, FastMoq.Provider.Moq, or FastMoq.Provider.NSubstitute -- inspect shared helpers and base classes before leaf tests, especially `.Object`, `.Reset()`, `Func`, and framework service-provider setup such as `FunctionContext.InstanceServices` -- identify Moq-specific dependencies such as GetMock(), direct Mock, Setup(...), SetupSet(...), SetupAllProperties(), Protected(), VerifyLogger(...), and out/ref verification -- identify web helpers, DbContext helpers, and HTTP compatibility helpers that imply package boundaries - -Migration rules: -- prefer GetOrCreateMock(), GetObject(), Verify(...), VerifyNoOtherCalls(...), VerifyLogged(...), and TimesSpec when that makes the test clearer -- treat obsolete APIs such as GetMock(), VerifyLogger(...), Initialize(...), and MockOptional as migration targets, not the preferred end state -- replace GetMock() with GetOrCreateMock() plus provider-package extensions such as AsMoq() unless the test still truly requires raw Mock-shaped compatibility -- keep Moq-specific behavior on Moq when the test still depends on Moq-only semantics -- for NSubstitute migration, replace Moq Setup(...) syntax with native NSubstitute arrangement syntax -- for controller or HttpContext tests, prefer FastMoq.Web helpers such as CreateHttpContext(...), CreateControllerContext(...), SetupClaimsPrincipal(...), AddHttpContext(...), and AddHttpContextAccessor(...) -- if exact custom claims matter, use TestClaimsPrincipalOptions with IncludeDefaultIdentityClaims = false -- if local repo helpers overlap with FastMoq.Web helpers, re-point the local wrappers first and simplify later only if it improves clarity -- do not force provider-neutral rewrites where Moq compatibility is still the clearer path, but still remove obsolete entry points where a v4 replacement exists - -For this batch: -- explain the package and provider assumptions you found -- explain which tests should stay on Moq and which can move toward provider-neutral APIs -- convert obsolete APIs to their v4 replacements wherever the test intent stays clear -- make the smallest safe edits needed -- list any obsolete usages that remain and the exact blocker for each one -``` - -Use this version for incremental migration. Stabilize first if the suite is still red. Once it is stable, treat obsolete removal as the default for touched tests and leave compatibility APIs only where a real blocker remains. - -## Strict obsolete-cleanup prompt - -Use this version when the goal is to keep the suite passing and remove obsolete FastMoq entry points from every touched file unless a concrete blocker remains. - -```text -I am migrating this FastMoq test file to the current v4 APIs. - -Use these docs, in order, as the source of truth: -- Main migration guide and routing: https://github.com/cwinland/FastMoq/blob/master/docs/migration/README.md -- API replacements and migration exceptions: https://github.com/cwinland/FastMoq/blob/master/docs/migration/api-replacements-and-exceptions.md -- Provider bootstrap, package boundaries, and Moq-to-NSubstitute translation: https://github.com/cwinland/FastMoq/blob/master/docs/migration/provider-and-compatibility.md -- Framework helpers, FastMoq.Web migration, claims-principal guidance, keyed DI, and FunctionContext.InstanceServices: https://github.com/cwinland/FastMoq/blob/master/docs/migration/framework-and-web-helpers.md - -If only one doc can be provided, use the main migration guide. If two can be provided, use the main migration guide and API replacements doc. - -Treat obsolete FastMoq APIs as migration defects to remove from this file unless there is a documented blocker. - -Before editing: -- inspect package references and active provider assumptions -- inspect shared helpers or base classes first if the file depends on them -- identify every use of GetMock(), VerifyLogger(...), Initialize(...), MockOptional, and other obsolete or compatibility-only FastMoq APIs in this file -- identify any Moq-only behavior that still requires provider-specific handling - -Editing rules: -- replace obsolete FastMoq APIs with current v4 equivalents wherever possible -- prefer GetOrCreateMock(), GetObject(), Verify(...), VerifyNoOtherCalls(...), VerifyLogged(...), TimesSpec, AddType(...), and FastMoq.Web helpers where appropriate -- use GetOrCreateMock().AsMoq() or direct provider-package extensions instead of leaving GetMock() behind when the test still needs Moq semantics -- only keep an obsolete call if the file still depends on a compatibility-only shape with no clean v4 replacement in that test - -Output expectations: -- make the smallest safe edits needed -- list every obsolete usage that was replaced -- list every obsolete usage that remains and explain the specific blocker for each one -``` - -Use the strict variant after the first stabilization pass. It is for touched-file cleanup, not the earliest "just get the suite green" phase. diff --git a/docs/migration/provider-and-compatibility.md b/docs/migration/provider-and-compatibility.md index 23a52696..aa6426cc 100644 --- a/docs/migration/provider-and-compatibility.md +++ b/docs/migration/provider-and-compatibility.md @@ -73,6 +73,8 @@ Current fallback rule of thumb: For example, `GetMock()`, direct `Mock` access, `VerifyLogger(...)`, and `Protected()` still mean `moq`, while `AsNSubstitute()` and `Received(...)` mean `nsubstitute`. +When a migrated suite still depends on one of those provider-specific surfaces, the safest stabilization step is an explicit assembly default. + For the built-in `moq` provider, and for `nsubstitute` after its package is referenced, the shortest path is [FastMoqDefaultProviderAttribute](https://help.fastmoq.com/api/FastMoq.Providers.FastMoqDefaultProviderAttribute.html): ```csharp @@ -81,93 +83,13 @@ using FastMoq.Providers; [assembly: FastMoqDefaultProvider("moq")] ``` -That attribute works with xUnit too; it is not tied to a particular test framework. It selects the default provider by canonical name during FastMoq bootstrap. - -When the provider must be registered and selected together at assembly scope, use [FastMoqRegisterProviderAttribute](https://help.fastmoq.com/api/FastMoq.Providers.FastMoqRegisterProviderAttribute.html): - -```csharp -using FastMoq.Providers; -using FastMoq.Providers.MoqProvider; - -[assembly: FastMoqRegisterProvider("moq", typeof(MoqMockingProvider), SetAsDefault = true)] -``` - -That form registers the provider type and makes it the assembly default during FastMoq bootstrap, without depending on a framework-specific startup hook. - -Use the startup-code examples below only when you need more than declarative assembly metadata. Common cases are: - -- choosing the provider dynamically at runtime from configuration, environment, or target-specific logic -- combining provider selection with other one-time test bootstrap work in the same startup path -- running custom registration logic that cannot be expressed as a provider type plus `SetAsDefault` - -### Copy-paste startup-hook examples +That selects the default provider by canonical name during FastMoq bootstrap. The same attribute form works regardless of the test framework because FastMoq reads it during its own provider bootstrap. -#### xUnit +When registration and selection need to happen together, or when startup must be dynamic, use the canonical forms in [Provider Selection and Setup](../getting-started/provider-selection.md#explicit-assembly-default-when-the-suite-must-not-depend-on-discovery). That page owns the full mechanics for: -If you need startup code in xUnit, a module initializer is a portable option that works well for provider registration and default-provider selection. Consumers on xUnit v3 may also choose assembly fixtures or test pipeline startup when those fit their broader test-bootstrap model: - -```csharp -using System.Runtime.CompilerServices; -using FastMoq.Providers; -using FastMoq.Providers.MoqProvider; - -namespace MyTests; - -public static class TestAssemblyProviderBootstrap -{ - [ModuleInitializer] - public static void Initialize() - { - MockingProviderRegistry.Register("moq", MoqMockingProvider.Instance, setAsDefault: true); - } -} -``` - -Module-initializer note: - -- some analyzers warn on `[ModuleInitializer]` usage in test projects, commonly `CA2255` -- for a dedicated test bootstrap type, a targeted suppression is an expected choice when you intentionally use the module-initializer pattern -- if your framework already offers a one-time assembly startup hook, use that hook instead of forcing the xUnit pattern into every test project - -#### NUnit - -```csharp -using FastMoq.Providers; -using FastMoq.Providers.MoqProvider; -using NUnit.Framework; - -namespace MyTests; - -[SetUpFixture] -public sealed class TestAssemblyProviderBootstrap -{ - [OneTimeSetUp] - public void Initialize() - { - MockingProviderRegistry.Register("moq", MoqMockingProvider.Instance, setAsDefault: true); - } -} -``` - -#### MSTest - -```csharp -using FastMoq.Providers; -using FastMoq.Providers.MoqProvider; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace MyTests; - -[TestClass] -public sealed class TestAssemblyProviderBootstrap -{ - [AssemblyInitialize] - public static void Initialize(TestContext _) - { - MockingProviderRegistry.Register("moq", MoqMockingProvider.Instance, setAsDefault: true); - } -} -``` +- `[assembly: FastMoqRegisterProvider(...)]` when the provider must be registered and selected together at assembly scope +- startup hooks for xUnit, NUnit, MSTest, or other frameworks when provider choice is dynamic or must be combined with other one-time bootstrap work +- the broader resolution rules around discovery, explicit defaults, and scoped overrides Migration guidance for v4: diff --git a/docs/roadmap/README.md b/docs/roadmap/README.md index e118027d..2215d0f6 100644 --- a/docs/roadmap/README.md +++ b/docs/roadmap/README.md @@ -1,25 +1,32 @@ # FastMoq Roadmap -This page summarizes the planned FastMoq priorities for upcoming releases. It focuses on future work rather than repeating completed migration steps. +This page summarizes the current public FastMoq direction for upcoming releases. It stays focused on future work, known major-version cleanup, and areas still under evaluation. -## Planned for v4 +Only a small part of the release split is fixed right now. The main decided v5 items are the planned core packaging cleanup, obsolete-surface removal, and code-generation work. Other work may land in additional v4 releases or in a later major version depending on stability, package boundaries, and documentation readiness. + +For current package behavior, provider availability, and already shipped features, use the getting-started, provider-selection, and what's-new docs instead of this page. + +This page tracks public FastMoq product direction only. Internal maintainer work such as local test-stack migration, internal runner experiments, or other repository-only operational tasks is intentionally excluded even when that work still matters inside this repo. + +## Near-term direction ### Provider-neutral release hardening -v4 work will continue to sharpen the provider boundary so shared FastMoq behavior stays portable and provider-specific behavior stays explicit. +Near-term work will continue to sharpen the provider boundary so shared FastMoq behavior stays portable and provider-specific behavior stays explicit. -Planned focus areas: +Active focus areas include: - Further reduce reliance on Moq-shaped compatibility paths in shared core flows. - Keep provider-native access available without requiring every provider to emulate Moq. -- Harden packaging and provider-selection guidance for the built-in Moq, NSubstitute, and reflection providers. +- Expand provider-first setup and verification methods where a shared FastMoq surface can stay clear and useful without hiding real provider differences. +- Improve packaging and provider-selection guidance for the current provider lineup, aggregate-package behavior, and optional provider packages. - Tighten migration guidance for compatibility surfaces that remain in v4 but are not intended to define the long-term API shape. ### Analyzer expansion -The remaining non-web analyzer work is planned for v4 where the guidance is stable enough to stay low-noise and useful in everyday test authoring. +The remaining non-web analyzer work stays on the near-term roadmap where the guidance is stable enough to stay low-noise and useful in everyday test authoring. -Planned analyzer work includes: +Likely analyzer work includes: - Distinguishing between tests that should use `GetOrCreateMock()` and tests that should intentionally replace resolution with `AddType(...)` or `AddKnownType(...)`. - Guiding suites away from one-object-for-all-types service-provider shims once the typed `IServiceProvider` helper is available. @@ -27,40 +34,33 @@ Planned analyzer work includes: ### Test helpers and migration support -v4 also includes helper and migration work where common testing scenarios still need a first-party answer rather than documentation alone. +Helper and migration work remains active where common testing scenarios still need a first-party answer rather than documentation alone. -Planned work includes: +Current follow-up areas include: +- Additional provider-first setup and verification helpers where current suites still drop into provider-native syntax too early. - Additional provider-neutral guidance for framework-heavy suites that combine typed `IServiceProvider` helpers with keyed services or framework-owned service graphs beyond the current scope-aware helper path. - Azure Functions follow-up helpers beyond the shipped `FunctionContext.InstanceServices`, `CreateHttpRequestData(...)`, and `CreateHttpResponseData(...)` support. - Focused migration guidance and examples for compatibility-only APIs that remain temporary rather than long-term patterns. -Recently added in the current v4 line: - -- `AddPropertyState(...)` for common interface-based `SetupAllProperties()` migration cases where the real need is lightweight stateful property backing. -- `CreateTypedServiceScope(...)` and `AddServiceScope(...)` for typed scope setup, plus optional `includeMockerFallback: true` bridging when framework-owned resolution should fall back to normal `Mocker` behavior. -- `FMOQ0013` coverage for manual `IServiceScopeFactory` and `IServiceScope` shims, alongside the existing typed `IServiceProvider` guidance. -- `FMOQ0021` guidance for Moq `SetupAllProperties()` cases that should move toward `AddPropertyState(...)` or a concrete fake. +Current public issue anchors in this bucket include [#41](https://github.com/cwinland/FastMoq/issues/41) for structured diagnostics and [#107](https://github.com/cwinland/FastMoq/issues/107) for remaining Azure Functions execution-context follow-up. -Other gaps worth adding next, in priority order: - -1. Azure Functions follow-up helpers beyond `InstanceServices`, request, and response. -2. More examples and sample-backed docs for property-capture and property-state migration. -3. Additional keyed-service guidance for framework-owned DI graphs. +Examples, migration docs, and analyzer guidance are more likely to move first than broad new helper surfaces when the release split is still being evaluated. ### Documentation and examples -v4 documentation work will focus on the features and migration paths that still need stronger release-facing guidance. +Documentation work remains part of the near-term plan because several provider-dependent and helper-heavy scenarios still need stronger release-facing guidance. -Planned documentation updates include: +Likely documentation work includes: - More provider-native examples beyond the current capability matrix. +- Expanded feature-parity guidance for provider-dependent sequence, call-order, event, and advanced setup scenarios where the current shared FastMoq surface intentionally stops short of a single abstraction. - Focused migration notes for older Moq-heavy suites. - Keyed-service guidance tied to new diagnostics and helper APIs. - Examples for typed service-provider flows and broader Azure testing helpers, including HTTP-trigger request or response setup. - Additional DbContext examples as those surfaces continue to harden. -## Later or decision pending +## Later v5 work or timing still open ### Web and UI expansion @@ -85,16 +85,66 @@ Planned follow-up includes: ## Planned v5 Cleanup +### Core packaging and provider defaults + +The current v5 direction is to keep `FastMoq.Core` provider-neutral and move bundled provider availability to the aggregate package instead of core. + +Current public issue anchor in this bucket is [#140](https://github.com/cwinland/FastMoq/issues/140). + +Planned follow-up includes: + +- Removing the current built-in Moq provider path from `FastMoq.Core`. +- Keeping provider implementations such as Moq and NSubstitute available through the aggregate `FastMoq` package. +- Keeping selective-install workflows available through explicit provider packages. +- Tightening provider-selection guidance so package composition stays predictable as the core or aggregate boundaries change. + +### Provider expansion + +Provider expansion remains part of the current v5 direction once the provider boundary and package model are stable enough to support another first-party provider cleanly. + +Planned follow-up includes: + +- evaluating a first-party FakeItEasy provider as a distinct provider-expansion track rather than folding it into the generator backlog +- keeping parity docs explicit that FakeItEasy is currently a direct-framework comparison baseline, not a shipped FastMoq provider +- tracking the FakeItEasy provider work through [#128](https://github.com/cwinland/FastMoq/issues/128) instead of leaving it only in roadmap prose + ### Obsolete and compatibility surface cleanup A future major-version cleanup will continue reducing Moq-oriented compatibility members that remain only to ease migration. The goal is a smaller, clearer public surface where provider-first APIs are the default path and compatibility shims are no longer carrying day-to-day guidance. +Current public issue anchor in this bucket is [#141](https://github.com/cwinland/FastMoq/issues/141). + +### Code generation and scaffolding + +First-party code generators do not exist today, but code-generation work is part of the current v5 direction. + +The main value is not "generated mocks" in isolation. The stronger FastMoq-specific opportunity is compile-time provider-first test generation: generated test graphs, harness scaffolding, and framework-helper builders that reduce reflection, reduce boilerplate, and stay aligned with FastMoq-owned APIs. + +Current public issue crosswalk: + +- foundation and package-shape work: [#120](https://github.com/cwinland/FastMoq/issues/120), [#121](https://github.com/cwinland/FastMoq/issues/121), [#125](https://github.com/cwinland/FastMoq/issues/125), [#126](https://github.com/cwinland/FastMoq/issues/126), [#127](https://github.com/cwinland/FastMoq/issues/127), and [#134](https://github.com/cwinland/FastMoq/issues/134) +- near-term helper preparation that can improve v4 authoring before generators ship: [#132](https://github.com/cwinland/FastMoq/issues/132), [#133](https://github.com/cwinland/FastMoq/issues/133), and [#135](https://github.com/cwinland/FastMoq/issues/135) +- first implementation-facing outcomes: [#122](https://github.com/cwinland/FastMoq/issues/122), [#136](https://github.com/cwinland/FastMoq/issues/136), [#137](https://github.com/cwinland/FastMoq/issues/137), [#123](https://github.com/cwinland/FastMoq/issues/123), and [#124](https://github.com/cwinland/FastMoq/issues/124) +- later evaluation tracks after the provider-first generator story is stable: [#138](https://github.com/cwinland/FastMoq/issues/138) and [#139](https://github.com/cwinland/FastMoq/issues/139) + +Planned direction stays phased: + +1. Compile-time test graph and harness generation. +2. Scenario and suite scaffolding. +3. Framework-helper builders and fuller generated tests from existing supported classes. +4. Analyzer-guided generation flow and package suggestions. +5. Provider-optimized or narrower generated-fake evaluation only after the shared contract is stable. + +For the current detailed direction, design constraints, and fuller generator issue mapping, see [Generator roadmap and design](./generator-roadmap.md). + ### `MockOptional` retirement FastMoq will continue moving optional-parameter guidance toward explicit controls such as `Mocker.OptionalParameterResolution`, `InvocationOptions`, and focused `MockerTestBase` construction overrides. +Current public issue anchor in this bucket is [#142](https://github.com/cwinland/FastMoq/issues/142). + Planned follow-up includes: - Rewriting any remaining compatibility-only `MockOptional` examples. diff --git a/docs/roadmap/generator-roadmap.md b/docs/roadmap/generator-roadmap.md new file mode 100644 index 00000000..6d696f2e --- /dev/null +++ b/docs/roadmap/generator-roadmap.md @@ -0,0 +1,349 @@ +# FastMoq Generator Roadmap And Design + +This page captures the current v5 direction for FastMoq code generation. It is the detailed design companion to the main [roadmap summary](./README.md), not a shipped feature guide. + +This page is intentionally design-level only. It is appropriate for roadmap and implementation planning ahead of code, but it does not imply current shipped support. + +FastMoq does not currently include traditional Roslyn source generators. The current repo ships analyzers and code fixes, but it does not emit new `.g.cs` files for mocks, dependency graphs, or test scaffolding. + +## Current Baseline + +Confirmed current state: + +- `FastMoq.Analyzers` ships analyzers and code fixes for migration, provider-first authoring, package guidance, and helper adoption. +- The repo does not currently contain `ISourceGenerator` or `IIncrementalGenerator` implementations. +- There is no first-party compile-time generation of mocks, DI graphs, scenario scaffolding, or framework-helper builders. + +That means code generation in v5 is net-new product surface rather than a minor extension of the current analyzer package. + +## Public Issue Crosswalk + +The current public backlog for this design is: + +- [#120](https://github.com/cwinland/FastMoq/issues/120) `FastMoq.Generators` package shape and MVP contract +- [#121](https://github.com/cwinland/FastMoq/issues/121) runtime prerequisite umbrella for generator-targeted output +- [#132](https://github.com/cwinland/FastMoq/issues/132) provider-first setup helpers for common generator-friendly arrangements +- [#133](https://github.com/cwinland/FastMoq/issues/133) provider-first verification helpers for stable shared abstractions +- [#135](https://github.com/cwinland/FastMoq/issues/135) v4 quick helper-surface cleanups for logging, HTTP, and typed DI +- [#125](https://github.com/cwinland/FastMoq/issues/125) graph metadata hooks and constructor-selection primitives +- [#126](https://github.com/cwinland/FastMoq/issues/126) `ScenarioBuilder` scaffolding hooks for generated output +- [#127](https://github.com/cwinland/FastMoq/issues/127) package-detection and target-test-shape rules for generated tests +- [#134](https://github.com/cwinland/FastMoq/issues/134) blocking helper-surface normalization for logging, HTTP, Azure, Azure Functions, and typed DI +- [#122](https://github.com/cwinland/FastMoq/issues/122) compile-time graph and harness MVP +- [#136](https://github.com/cwinland/FastMoq/issues/136) generated scenario and suite scaffolding after the graph and harness MVP +- [#137](https://github.com/cwinland/FastMoq/issues/137) generator-backed framework-helper builders for repeated test patterns +- [#123](https://github.com/cwinland/FastMoq/issues/123) full provider-first test generation from existing services and supported classes +- [#124](https://github.com/cwinland/FastMoq/issues/124) analyzer-guided test generation and missing-package suggestions +- [#138](https://github.com/cwinland/FastMoq/issues/138) later provider-optimized generation evaluation +- [#139](https://github.com/cwinland/FastMoq/issues/139) later narrow compile-time fake or mock generation evaluation + +Crosswalk summary: + +- `#121` is the runtime-prerequisite umbrella. +- `#132`, `#133`, and `#135` are the narrower v4-style quick wins that can improve normal authoring before generators ship. +- `#120`, `#125`, `#126`, `#127`, and `#134` are the pre-v5 contract and blocking prerequisite slices. +- `#122`, `#136`, `#137`, `#123`, and `#124` are the phased implementation and authoring-flow outcomes once the prerequisites are stable enough. +- `#138` and `#139` are intentionally late evaluation tracks after the main provider-first generator story is already working. + +## Product Positioning + +The generator story should not be framed as "FastMoq can generate mocks too." That is smaller than the architecture and easier to compare directly against provider-owned dynamic mocking behavior. + +The stronger FastMoq position is: + +- compile-time provider-first test generation +- compile-time test graph generation +- generated full tests from existing services and other classes +- generated harness and scenario scaffolding +- generated framework-helper builders for repeated integration-style test patterns + +That positioning fits what FastMoq already owns today: + +- provider-neutral construction and verification surfaces +- DI-aware object creation +- framework-heavy test helpers +- analyzer-guided authoring and migration + +## Design Principles + +Any v5 generator work should follow these rules: + +1. Target stable FastMoq-owned APIs first. +2. Prefer generated graphs, scaffolds, and builders before generated provider-specific mock behavior. +3. Keep provider-specific semantics explicit when they cannot be flattened cleanly. +4. Use generators to remove reflection, graph walking, and boilerplate where FastMoq already has runtime responsibility. +5. Avoid generating new compatibility-heavy wrappers that would keep older Moq-shaped usage alive longer than necessary. +6. Preserve a runtime fallback path when generated assets are not present. + +## Biggest Selling Point + +The flagship v5 message should be: + +FastMoq can generate provider-first test graphs, harness scaffolding, and framework-helper builders at compile time while still letting suites choose Moq, NSubstitute, or reflection-backed runtime behavior where needed. + +Why that matters: + +- less reflection during test setup +- less runtime graph walking +- less repeated harness boilerplate +- faster creation of correct first-pass tests for existing code that still has no FastMoq coverage +- more deterministic graph construction +- a stronger path for trimming and AOT-sensitive environments where FastMoq-owned generated code can replace reflection-heavy paths + +## Planned Generator Workstreams + +### 1. Compile-time test graph and harness generation + +This is the highest-value first workstream. + +Primary outputs: + +- generated constructor-chain metadata +- generated dependency ordering +- generated harness bootstrap for selected components under test +- generated tracked-dependency accessors or helpers +- optional generated constructor-selection metadata where FastMoq already owns the runtime policy + +Why it goes first: + +- it aligns directly with FastMoq's DI-aware object-creation value +- it reduces reflection and graph walking without promising provider-neutral mock semantics that may not exist +- it creates a visible performance and ergonomics story for larger solutions + +### 2. Scenario and suite scaffolding + +This workstream should build on generated graph metadata rather than replace it. + +Primary outputs: + +- generated scenario shell types or partials +- generated per-suite setup regions +- generated default verify helpers or scenario hooks +- generated migration-starting points for repeated patterns + +Expected value: + +- less repetitive suite boilerplate +- easier adoption of `ScenarioBuilder`-style flows +- clearer entry points for new tests in provider-first projects + +### 3. Full-test generation from existing services and classes + +This workstream should generate complete starting tests for real existing code, not just partial harness fragments. + +Primary outputs: + +- generated test classes for existing services, handlers, controllers, background services, and other supported component shapes +- generated arrange or act or assert skeletons that map to the current FastMoq package surfaces available in the consuming project +- generated package-aware imports and harness selection based on the installed FastMoq runtime and helper packages +- generated placeholders for unresolved seams when a full test cannot be completed safely + +Scope rule: + +- the generator should only emit tests that target FastMoq packages and helper surfaces already available in the current project unless the user explicitly accepts an analyzer-guided package addition path + +Expected value: + +- a large visible adoption win for existing projects that want to bootstrap provider-first tests quickly +- consistent first-pass tests that match FastMoq guidance instead of one-off local patterns +- a stronger story for moving from "no tests yet" to "generated provider-first tests plus manual refinement" + +### 4. Framework-helper builders + +This workstream should focus on high-friction areas where FastMoq already owns helper APIs. + +Likely targets: + +- `HttpClient` and request-helper builders +- Azure SDK client and pageable builders +- Azure Functions request or response builders +- logging verification helper builders +- typed `IServiceProvider` and scope bootstrap patterns + +Expected value: + +- lower friction in framework-heavy tests +- better reuse of existing FastMoq helper surfaces +- less local ad hoc builder code in consuming test suites + +### 5. Analyzer-guided test generation and package suggestions + +Generator work should be paired with analyzers so the authoring flow can start from real code that is not yet covered. + +Primary analyzer behaviors: + +- detect existing services or other supported classes that appear to have no neighboring FastMoq-style tests +- suggest generating a provider-first test when the current project already references the needed FastMoq package set +- suggest adding the correct test or helper packages when the target test shape depends on a missing FastMoq surface such as web, database, Azure, or Azure Functions helpers +- avoid firing when the generator would have to guess at unavailable helper packages or unsupported test frameworks + +Expected value: + +- makes generators discoverable from normal code-authoring flow instead of only from templates or docs +- connects package-aware analyzer guidance with the new code-generation path +- helps teams bootstrap missing tests in a controlled, FastMoq-owned way + +### 6. Provider-optimized generation + +Provider-specific optimization should be a later step, not the foundation. + +Possible outputs: + +- Moq-oriented generated setup or bootstrap fast paths +- NSubstitute-oriented generated bootstrap or arrangement helpers +- reflection-provider invocation-map generation where FastMoq fully owns the implementation + +This work should only move once the provider-first generator contract is stable. + +### 7. Narrow compile-time fake or mock generation + +This is the most exploratory workstream and should stay last in priority. + +Why it is later: + +- direct compile-time mock generation risks overpromising provider-neutral behavior that still depends on provider-owned semantics +- it is easier to defend generated graphs and scaffolds publicly than broad generated-mock claims +- FastMoq's differentiator is broader than fake-object emission alone + +If pursued, it should start with the narrowest cases where FastMoq can keep the behavior predictable and provider-first. + +## Required Runtime Precondition Work + +Generator work should not outpace the runtime API surface it depends on. + +Before or alongside generator implementation, FastMoq likely needs: + +- expanded provider-first setup helpers for common simple arrangements +- expanded provider-first verification helpers where a shared abstraction is still clear and stable +- stable graph metadata hooks or reusable constructor-selection primitives for generator output +- clearer scenario-builder extension points for generated scaffolding +- generator-friendly helper surfaces for logging, HTTP, Azure, Azure Functions, and DI-heavy setup +- clear package-detection and target-test-shape rules so generated tests do not assume helper packages that are not referenced + +Without those runtime targets, generators would be forced to emit provider-native or compatibility-heavy code too early. + +### Likely v4 quick wins + +Some runtime preparation work is narrow enough that it could land before v5 if the implementation stays focused and does not force a wider public-contract redesign. + +Best candidates: + +- expanded provider-first setup helpers for common simple arrangements +- expanded provider-first verification helpers where a shared abstraction is still clear and stable +- small helper-surface cleanups for logging, HTTP, or typed DI setup where the FastMoq-owned runtime surface already exists and only needs a more generator-friendly shape + +These are valuable early because they improve normal authoring even before source generators ship. + +### Likely v5 blocking prerequisites + +Some work is more foundational and should be treated as explicit prerequisites for the generator implementation itself. + +Blocking areas: + +- stable graph metadata hooks or reusable constructor-selection primitives for generator output +- clearer scenario-builder extension points for generated scaffolding +- clear package-detection and target-test-shape rules so generated tests do not assume helper packages that are not referenced +- broader generator-friendly helper normalization across logging, HTTP, Azure, Azure Functions, and DI-heavy setup when generated output needs those shapes to stay consistent across projects + +Those pieces are less about convenience and more about preventing the generator from emitting unstable, provider-native, or package-guessing code. + +## Suggested Package Shape + +The likely package model is still under design, but the working direction is: + +- a new generator package, likely `FastMoq.Generators` +- optional shared attribute or contract types in `FastMoq.Abstractions` or a small generator-abstractions companion package if the main abstractions package becomes too broad for generator consumers +- analyzers and code fixes remaining separate from the source-generator implementation even if they are coordinated in behavior + +That separation keeps the current migration analyzer story intact while allowing generator-specific incremental compilation work to evolve independently. + +## Suggested v5 Delivery Phases + +### Phase 0: contract and package design + +Define: + +- package boundaries +- generator opt-in model +- runtime fallback behavior +- attribute or marker strategy +- baseline benchmark scenarios + +### Phase 1: graph and harness MVP + +Ship: + +- generated test graph metadata +- generated harness bootstrap for selected components +- initial benchmark coverage showing reduced reflection and setup overhead + +### Phase 2: scenario and scaffold generation + +Ship: + +- generated suite or scenario scaffolds +- generated migration or new-test starting points +- analyzer guidance that can offer "move to generated scaffold" suggestions where appropriate + +### Phase 3: full-test generation from existing code + +Ship: + +- generated full tests for supported existing services and other supported component shapes +- package-aware harness selection based on the FastMoq surfaces already referenced by the project +- analyzer suggestions that can offer "generate provider-first test" for supported untested code + +### Phase 4: framework-helper builders + +Ship: + +- targeted builders for repeated HTTP, Azure, Azure Functions, logging, and DI-heavy setup patterns + +### Phase 5: package-aware analyzer follow-up + +Ship: + +- analyzer guidance for supported untested code where the current project is missing the FastMoq package surface needed for the desired generated test shape +- suggestions that point to the correct package additions before generation is offered + +### Phase 6: provider-optimized and narrower generated-fake work + +Evaluate: + +- provider-specific optimization layers +- narrow compile-time fake or mock generation where FastMoq can keep the semantics predictable + +## Risks And Constraints + +The largest design risks are: + +- promising provider-neutral generated behavior where providers still differ materially +- coupling generator output too tightly to unstable runtime APIs +- turning source generation into a second compatibility surface instead of a provider-first accelerator +- overcommitting to AOT claims before the generated path is proven end to end +- generating low-value placeholder tests that look complete but do not map cleanly to the packages and helper surfaces actually installed in the project + +Because of that, the safest public promise is generated provider-first graphs and scaffolding first, broader generated-mock claims later only if the model still holds. + +## Recommended Issue Breakdown + +The current doc plan now maps to these issue slices: + +1. Define generator package shape, runtime contract, and MVP scope. +2. Coordinate the runtime prerequisite map across likely v4 quick wins and v5 blocking work. +3. Expand provider-first setup helpers for common simple arrangements. +4. Expand provider-first verification helpers where a shared abstraction is still clear and stable. +5. Tighten the existing logging, HTTP, and typed DI helper surfaces that are small enough to land as v4 quick wins. +6. Define graph metadata hooks and constructor-selection contracts for generator-targeted output. +7. Define `ScenarioBuilder` scaffolding hooks and regeneration-safe extension points for generated output. +8. Define package-detection and target-test-shape rules for package-aware generation. +9. Normalize the broader blocking helper surfaces for logging, HTTP, Azure, Azure Functions, and typed DI-heavy setup. +10. Implement compile-time test graph and harness generation MVP. +11. Implement generated scenario and suite scaffolding after the graph and harness MVP. +12. Implement generator-backed framework-helper builders for repeated test patterns. +13. Add full-test generation for supported existing services and other supported classes. +14. Add analyzer guidance for untested code plus package-aware suggestions before test generation. +15. Evaluate provider-optimized generation after the provider-first contract is stable. +16. Evaluate narrow compile-time fake or mock generation only for predictable provider-first cases. + +Those issue slices keep design, runtime prerequisites, MVP implementation, and analyzer or scaffolding follow-up separate enough to plan and sequence clearly without hiding important prerequisite work inside umbrella wording. diff --git a/toc.yml b/toc.yml index 113e5b47..16c6ea96 100644 --- a/toc.yml +++ b/toc.yml @@ -12,6 +12,12 @@ href: docs/getting-started/provider-capabilities.md - name: Testing guide href: docs/getting-started/testing-guide.md +- name: Feature Parity + href: docs/feature-parity/README.md +- name: AI-Assisted Workflows + items: + - name: AI prompt templates + href: docs/ai/README.md - name: Examples and Recipes items: - name: Cookbook @@ -36,12 +42,12 @@ href: docs/migration/framework-and-web-helpers.md - name: API replacements and migration exceptions href: docs/migration/api-replacements-and-exceptions.md - - name: Copilot migration prompts - href: docs/migration/copilot-prompts.md - name: Breaking changes href: docs/breaking-changes/README.md - name: Roadmap notes href: docs/roadmap/README.md + - name: Generator roadmap and design + href: docs/roadmap/generator-roadmap.md - name: API Reference items: - name: Quick reference