geoder101.MoqProxy.DependencyInjection.Microsoft 1.0.25-alpha

This is a prerelease version of geoder101.MoqProxy.DependencyInjection.Microsoft.
dotnet add package geoder101.MoqProxy.DependencyInjection.Microsoft --version 1.0.25-alpha
                    
NuGet\Install-Package geoder101.MoqProxy.DependencyInjection.Microsoft -Version 1.0.25-alpha
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="geoder101.MoqProxy.DependencyInjection.Microsoft" Version="1.0.25-alpha" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="geoder101.MoqProxy.DependencyInjection.Microsoft" Version="1.0.25-alpha" />
                    
Directory.Packages.props
<PackageReference Include="geoder101.MoqProxy.DependencyInjection.Microsoft" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add geoder101.MoqProxy.DependencyInjection.Microsoft --version 1.0.25-alpha
                    
#r "nuget: geoder101.MoqProxy.DependencyInjection.Microsoft, 1.0.25-alpha"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package geoder101.MoqProxy.DependencyInjection.Microsoft@1.0.25-alpha
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=geoder101.MoqProxy.DependencyInjection.Microsoft&version=1.0.25-alpha&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=geoder101.MoqProxy.DependencyInjection.Microsoft&version=1.0.25-alpha&prerelease
                    
Install as a Cake Tool

MoqProxy.DependencyInjection.Microsoft

NuGet

Microsoft.Extensions.DependencyInjection integration for MoqProxy - enabling proxy pattern mocking within ASP.NET Core and other dependency injection scenarios.

What is this?

This library provides extension methods to seamlessly integrate MoqProxy with Microsoft's dependency injection container. It allows you to wrap existing service registrations with Moq proxies for testing, enabling you to:

  • Verify calls to services registered in your DI container
  • Spy on real implementations without changing production code
  • Test integration scenarios with partial mocking
  • Observe service interactions in complex dependency graphs

Installation

dotnet add package geoder101.MoqProxy.DependencyInjection.Microsoft

Quick Start

using Microsoft.Extensions.DependencyInjection;
using Moq;

// Set up your services as usual
var services = new ServiceCollection();
services.AddSingleton<IEmailService, EmailService>();
services.AddSingleton<IUserService, UserService>();

// Wrap a service with a Moq proxy for testing
var emailMock = new Mock<IEmailService>();
services.AddMoqProxy(emailMock);

// Build and use the container
var provider = services.BuildServiceProvider();
var userService = provider.GetRequiredService<IUserService>();

// The UserService will receive the proxied EmailService
userService.RegisterUser("john@example.com");

// Verify the real EmailService was called through the proxy
emailMock.Verify(e => e.SendWelcomeEmail("john@example.com"), Times.Once);

How It Works

AddMoqProxy<TService>() decorates an existing service registration with a Moq proxy using the decorator pattern:

  1. Resolves the original service implementation from the container
  2. Sets up the mock as a proxy that forwards all calls to the original implementation
  3. Replaces the service registration with the mock object

This means:

  • ✅ The real implementation runs normally
  • ✅ You can verify all interactions via Moq
  • ✅ You can override specific behaviors if needed
  • ✅ Works with interfaces and classes

Usage Examples

Basic Service Proxying

var services = new ServiceCollection();
services.AddSingleton<ICalculator, Calculator>();

var mock = new Mock<ICalculator>();
services.AddMoqProxy(mock);

var provider = services.BuildServiceProvider();
var calculator = provider.GetRequiredService<ICalculator>();

// Calls are forwarded to the real Calculator implementation
var result = calculator.Add(2, 3); // Returns 5

// But you can still verify the call
mock.Verify(c => c.Add(2, 3), Times.Once);

Testing Service Dependencies

var services = new ServiceCollection();
services.AddSingleton<IRepository, Repository>();
services.AddSingleton<IBusinessLogic, BusinessLogic>(); // Depends on IRepository

// Proxy the repository to observe calls from BusinessLogic
var repoMock = new Mock<IRepository>();
services.AddMoqProxy(repoMock);

var provider = services.BuildServiceProvider();
var businessLogic = provider.GetRequiredService<IBusinessLogic>();

// Execute business logic that uses the repository
businessLogic.ProcessOrder(orderId: 123);

// Verify the repository was called correctly
repoMock.Verify(r => r.GetOrder(123), Times.Once);
repoMock.Verify(r => r.SaveOrder(It.IsAny<Order>()), Times.Once);

Selective Behavior Override

var services = new ServiceCollection();
services.AddSingleton<IPaymentGateway, StripePaymentGateway>();

var mock = new Mock<IPaymentGateway>();
services.AddMoqProxy(mock);

// Override specific behavior for testing
mock.Setup(p => p.IsAvailable()).Returns(false);

var provider = services.BuildServiceProvider();
var gateway = provider.GetRequiredService<IPaymentGateway>();

// Overridden behavior
Assert.False(gateway.IsAvailable()); // Returns false from setup

// Other calls still forward to StripePaymentGateway
gateway.ProcessPayment(amount: 100); // Calls real implementation

Integration Testing with ASP.NET Core

public class IntegrationTests : IClassFixture<WebApplicationFactory<Program>>
{
    [Fact]
    public async Task Registration_ShouldSendEmail()
    {
        // Arrange
        var emailMock = new Mock<IEmailService>();

        var factory = new WebApplicationFactory<Program>()
            .WithWebHostBuilder(builder =>
            {
                builder.ConfigureTestServices(services =>
                {
                    // Proxy the email service
                    services.AddMoqProxy(emailMock);
                });
            });

        var client = factory.CreateClient();

        // Act
        var response = await client.PostAsJsonAsync("/api/users/register", new { Email = "test@example.com" });

        // Assert
        response.EnsureSuccessStatusCode();
        emailMock.Verify(e => e.SendWelcomeEmail("test@example.com"), Times.Once);
    }
}

Multiple Service Proxying

var services = new ServiceCollection();
services.AddSingleton<ILogger, ConsoleLogger>();
services.AddSingleton<ICache, RedisCache>();
services.AddSingleton<IApi, ExternalApi>();

// Proxy multiple services
var loggerMock = new Mock<ILogger>();
var cacheMock = new Mock<ICache>();
var apiMock = new Mock<IApi>();

services.AddMoqProxy(loggerMock);
services.AddMoqProxy(cacheMock);
services.AddMoqProxy(apiMock);

var provider = services.BuildServiceProvider();

// All services are now proxied and verifiable
// ... run your test scenario ...

// Verify all interactions
loggerMock.Verify(l => l.Log(It.IsAny<string>()), Times.AtLeastOnce);
cacheMock.Verify(c => c.Get(It.IsAny<string>()), Times.Once);
apiMock.Verify(a => a.FetchData(), Times.Once);

Requirements

API Reference

AddMoqProxy<TService>

public static IServiceCollection AddMoqProxy<TService>(
    this IServiceCollection services,
    Mock<TService> mock)
    where TService : class

Parameters:

  • services - The service collection containing the service to proxy
  • mock - The Moq mock instance that will wrap the original implementation

Returns: The IServiceCollection for method chaining

Remarks:

  • The service must be registered before calling AddMoqProxy
  • The mock is automatically configured to proxy all calls using SetupAsProxy()
  • The original service lifetime (Singleton, Scoped, Transient) is preserved

Technical Requirements

  • .NET 8.0 or later - The library targets .NET 8.0
  • Microsoft.Extensions.DependencyInjection 9.0.10 or later
  • MoqProxy - The core proxy functionality (installed as a dependency)
  • Moq 4.20.72 or later

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

License

This project is licensed under the MIT License - see the LICENSE.txt file for details.


Co-authored with Artificial Intelligence

This repository is part of an ongoing exploration into human-AI co-creation.
The code, comments, and structure emerged through dialogue between human intent and LLM reasoning — reviewed, refined, and grounded in human understanding.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.25-alpha 36 11/4/2025
1.0.22-alpha 50 11/2/2025
1.0.12-alpha 110 10/21/2025
1.0.6-alpha 114 10/20/2025
1.0.1-alpha 119 10/19/2025