Skip to content

Latest commit

 

History

History
182 lines (132 loc) · 6.68 KB

File metadata and controls

182 lines (132 loc) · 6.68 KB

Moq.AutoMocker Source Generators

Moq.AutoMock includes built-in source generators that provide compile-time code generation to enhance your testing experience. These generators automatically create boilerplate test code and extension methods, saving you time and reducing repetitive testing code.

Available Generators

Moq.AutoMock includes several source generators:

Automatically generates constructor null-check tests for your classes.

Key Features:

  • Generates tests for each nullable constructor parameter
  • Supports MSTest, xUnit, NUnit, and TUnit testing frameworks
  • Validates ArgumentNullException is thrown with correct parameter names
  • Provides customization hooks for test setup

Quick Example:

[TestClass]
[ConstructorTests(TargetType = typeof(MyController))]
public partial class MyControllerTests
{
}

Learn more →

Generates WithOptions<T>() extension method when Microsoft.Extensions.Options is referenced.

Key Features:

  • Fluent API for configuring options in tests
  • Sets up complete options infrastructure (IOptionsMonitor, IOptionsSnapshot, etc.)
  • Simplifies testing of classes that depend on IOptions<T>

Quick Example:

mocker.WithOptions<MySettings>(options => 
{
    options.Number = 42;
    options.Required = "test value";
});

Learn more →

Generates WithFakeLogging() extension method when Microsoft.Extensions.Diagnostics.Testing is referenced.

Key Features:

  • Captures log messages for verification
  • Uses Microsoft's official testing helpers
  • Enables logging behavior validation in tests

Quick Example:

mocker.WithFakeLogging();
var provider = mocker.Get<FakeLoggerProvider>();

// ... perform actions ...

var logs = provider.Collector.GetSnapshot();
Assert.IsTrue(logs.Any(log => log.Message == "Expected message"));

Learn more →

Generates WithApplicationInsights() and related extension methods when Microsoft.ApplicationInsights is referenced. Supports both 2.x and 3.x versions of Application Insights.

Key Features:

  • Application Insights 2.x: Uses a FakeTelemetryChannel with GetSentTelemetry() to capture ITelemetry items
  • Application Insights 3.x: Uses OpenTelemetry in-memory exporters with GetApplicationInsightsLogRecords(), GetApplicationInsightsMetrics(), and GetApplicationInsightsActivities()

Quick Example (3.x):

mocker.WithApplicationInsights();
var service = mocker.CreateInstance<MyService>();
service.DoWork();

var logRecords = mocker.GetApplicationInsightsLogRecords();
Assert.HasCount(2, logRecords);

Learn more →

Generates WithKeyedService<T>() extension methods when Microsoft.Extensions.DependencyInjection is referenced.

Key Features:

  • Enables testing of keyed services via IKeyedServiceProvider
  • Supports [FromKeyedServices] attribute resolution
  • Provides both eager and lazy service registration
  • Integrates seamlessly with dependency injection

Quick Example:

mocker.WithKeyedService(Mock.Of<IEmailSender>(), "primary");
mocker.WithKeyedService<ICache, RedisCache>("cache");

var service = mocker.CreateInstance<MyService>();
// Keyed services are automatically resolved

Learn more →

Important: Generated Classes Are Internal Partials

All extension classes created by these source generators are generated as partial classes with internal visibility. For example, the Keyed Services generator produces:

internal static partial class AutoMockerKeyedServicesExtensions
{
    // Generated extension methods...
}

Ambiguous Reference Issues with Multiple Test Projects

This design can cause ambiguous method call errors when multiple test projects reference each other and both have the source generators enabled. Since each project generates its own internal partial class with the same name and methods, projects that share visibility (e.g., via InternalsVisibleTo or project references) may see duplicate definitions.

Example error:

The call is ambiguous between the following methods or properties:
'Moq.AutoMock.AutoMockerKeyedServicesExtensions.WithKeyedService(...)' and
'Moq.AutoMock.AutoMockerKeyedServicesExtensions.WithKeyedService(...)'

This commonly occurs when:

  • An integration test project references a unit test project
  • InternalsVisibleTo is used between test projects
  • Both projects reference Moq.AutoMock and the same packages that trigger generators (e.g., Microsoft.Extensions.DependencyInjection.Abstractions)

Solution: Disable the source generator in one of the projects (see Disabling Source Generators below).

For more details, see Issue #410.

Disabling Source Generators

Each source generator can be individually disabled using MSBuild properties in your project's .csproj file:

Generator MSBuild Property
Options Extension EnableMoqAutoMockerOptionsGenerator
Keyed Services Extension EnableMoqAutoMockerKeyedServicesGenerator
Fake Logging Extension EnableMoqAutoMockerFakeLoggingGenerator
Application Insights Extension EnableMoqAutoMockerApplicationInsightsGenerator

Example: Disabling a generator

<PropertyGroup>
  <!-- Disable the Keyed Services generator -->
  <EnableMoqAutoMockerKeyedServicesGenerator>false</EnableMoqAutoMockerKeyedServicesGenerator>
</PropertyGroup>

Example: Disabling multiple generators

<PropertyGroup>
  <EnableMoqAutoMockerKeyedServicesGenerator>false</EnableMoqAutoMockerKeyedServicesGenerator>
  <EnableMoqAutoMockerOptionsGenerator>false</EnableMoqAutoMockerOptionsGenerator>
</PropertyGroup>

Tips and Best Practices

Review Generated Code

To see the generated code, enable source generators output in your .csproj:

<PropertyGroup>
  <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
  <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>