MockLite 1.0.7

dotnet add package MockLite --version 1.0.7
                    
NuGet\Install-Package MockLite -Version 1.0.7
                    
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="MockLite" Version="1.0.7" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MockLite" Version="1.0.7" />
                    
Directory.Packages.props
<PackageReference Include="MockLite" />
                    
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 MockLite --version 1.0.7
                    
#r "nuget: MockLite, 1.0.7"
                    
#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 MockLite@1.0.7
                    
#: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=MockLite&version=1.0.7
                    
Install as a Cake Addin
#tool nuget:?package=MockLite&version=1.0.7
                    
Install as a Cake Tool

MockLite

<p align="center"> <img src="logo.png" alt="MockLite Logo" width="256" /> </p>

NuGet License: MIT

MockLite is a lightweight, fast, and easy-to-use mocking framework for .NET with a fluent interface. It provides essential mocking capabilities without the complexity and overhead of larger frameworks.

Features

  • 🚀 Lightweight and Fast - Minimal overhead with dynamic proxy generation
  • 🎯 Simple API - Clean, fluent interface that's straightforward to learn and use
  • 🔧 Method Mocking - Mock methods with return values, callbacks, and exceptions
  • 📚 Sequential Setups - Define different behaviors for successive calls
  • 🏠 Property Mocking - Mock property getters and setters
  • Async Support - First-class support for async methods and Tasks
  • Verification - Verify method calls with flexible timing constraints
  • 🎯 Argument Matchers - Use It.IsAny<T>() and It.Is<T>(expression) for flexible parameter matching
  • 🎪 No Dependencies - Zero external dependencies

Installation

Install MockLite via NuGet:

dotnet add package MockLite

Or using the Package Manager Console:

Install-Package MockLite

Quick Start

using MockLite;

// Create a mock for your interface
var mock = new Mock<IOrderService>();

// Setup method behavior
mock.Setup(x => x.ValidateOrder(12345))
    .Returns(true);

// Use the mock object
var result = mock.Object.ValidateOrder(12345);
Assert.True(result);

// Verify method was called
mock.Verify(x => x.ValidateOrder(12345), Times.Once);

Usage Examples

Basic Method Mocking

public interface IPaymentService
{
    bool ProcessPayment(decimal amount, string cardNumber);
    decimal CalculateFee(decimal amount);
    void LogTransaction(string transactionId);
}

var mock = new Mock<IPaymentService>();

// Mock method with return value
mock.Setup(x => x.ProcessPayment(100.50m, "1234-5678-9012-3456"))
    .Returns(true);

// Mock method that throws exception
mock.Setup(x => x.ProcessPayment(0, "invalid-card"))
    .Throws<ArgumentException>();

// Mock void method with callback
var loggedTransactions = new List<string>();
mock.Setup(x => x.LogTransaction("TXN-123"))
    .Callback((string id) => loggedTransactions.Add(id));

Property Mocking

public interface IConfiguration
{
    string ApiEndpoint { get; set; }
    int Timeout { get; }
}

var mock = new Mock<IConfiguration>();

// Setup property getter
mock.SetupGet(x => x.ApiEndpoint)
    .Returns("https://api.example.com");

// Setup property setter with callback
var setValues = new List<string>();
mock.SetupSet(x => x.ApiEndpoint)
    .Callback((string value) => setValues.Add(value));

// Use the mock
var endpoint = mock.Object.ApiEndpoint; // Returns "https://api.example.com"
mock.Object.ApiEndpoint = "https://new-api.example.com"; // Triggers callback

Sequential Behaviors

For methods that should behave differently on successive calls:

public interface IRetryService
{
    bool TryConnect();
    string GetStatus();
}

var mock = new Mock<IRetryService>();

// Setup sequence for retry logic
mock.SetupSequence(x => x.TryConnect())
    .Returns(false)           // First call fails
    .Returns(false)           // Second call fails  
    .Returns(true);           // Third call succeeds

// Setup sequence with mixed behaviors
mock.SetupSequence(x => x.GetStatus())
    .Returns("Connecting")
    .Returns("Retrying")
    .Throws<TimeoutException>();

Async Method Support

public interface IAsyncService
{
    Task<string> FetchDataAsync(int id);
    Task ProcessAsync(string data);
}

var mock = new Mock<IAsyncService>();

// Mock async method with return value
mock.Setup(x => x.FetchDataAsync(123))
    .ReturnsAsync("Sample Data");

// Mock async void method
mock.Setup(x => x.ProcessAsync("test"))
    .Returns(Task.CompletedTask);

// Use async setup sequences
mock.SetupSequence(x => x.FetchDataAsync(456))
    .ReturnsAsync("First Result")
    .ReturnsAsync("Second Result")
    .ThrowsAsync<HttpRequestException>();

Verification

Verify that methods were called with expected parameters and frequency:

var mock = new Mock<IEmailService>();

// Perform operations
mock.Object.SendEmail("user@example.com", "Subject", "Body");
mock.Object.SendEmail("admin@example.com", "Alert", "Message");

// Verify exact calls
mock.Verify(x => x.SendEmail("user@example.com", "Subject", "Body"), Times.Once);

// Verify total call count (requires setup for each specific call)
mock.Setup(x => x.SendEmail("user@example.com", "Subject", "Body")).Verifiable();
mock.Setup(x => x.SendEmail("admin@example.com", "Alert", "Message")).Verifiable();

// Verify with different constraints
mock.Verify(x => x.SendEmail("user@example.com", "Subject", "Body"), Times.AtLeastOnce);
mock.Verify(x => x.SendEmail("unknown@example.com", "Unknown", "Unknown"), Times.Never);

Callbacks

Execute custom logic when methods are called:

public interface IAuditService
{
    void LogAction(string action, string user);
    bool ValidateUser(string username);
}

var mock = new Mock<IAuditService>();
var auditLog = new List<string>();

// Callback with parameters
mock.Setup(x => x.LogAction("login", "john_doe"))
    .Callback((string action, string user) => 
        auditLog.Add($"{DateTime.Now}: {user} performed {action}"));

// Callback with return value
mock.Setup(x => x.ValidateUser("john_doe"))
    .Returns(true)
    .Callback((string username) => Console.WriteLine($"Validating user: {username}"));

Argument Matchers

Use It.IsAny<T>() and It.Is<T>(expression) for flexible parameter matching:

public interface IOrderService
{
    bool ValidateOrder(int orderId);
    decimal CalculateShipping(decimal weight, string destination);
    void ProcessOrder(Order order);
}

var mock = new Mock<IOrderService>();

// Match any integer value
mock.Setup(x => x.ValidateOrder(It.IsAny<int>()))
    .Returns(true);

// Match based on condition
mock.Setup(x => x.ValidateOrder(It.Is<int>(id => id > 0)))
    .Returns(true);

// Mix specific values with matchers
mock.Setup(x => x.CalculateShipping(It.Is<decimal>(w => w > 0), It.IsAny<string>()))
    .Returns(15.99m);

// Complex conditions
mock.Setup(x => x.CalculateShipping(
        It.Is<decimal>(weight => weight > 0 && weight < 100),
        It.Is<string>(dest => dest.StartsWith("US"))))
    .Returns(12.50m);

// Test the setups
var result1 = mock.Object.ValidateOrder(123);     // Returns true (matches It.IsAny<int>())
var result2 = mock.Object.ValidateOrder(-1);      // Returns false (doesn't match It.Is<int>(id => id > 0))
var shipping = mock.Object.CalculateShipping(5.0m, "US-CA"); // Returns 12.50m

Real-World E-commerce Example

public interface IOrderService
{
    Task<decimal> CalculateOrderTotalAsync(int orderId);
    Task<bool> ProcessOrderAsync(Order order);
    void NotifyCustomer(string email, string message);
    bool ValidateInventory(int productId, int quantity);
}

public class OrderProcessor
{
    private readonly IOrderService _orderService;

    public OrderProcessor(IOrderService orderService)
    {
        _orderService = orderService;
    }

    public async Task<bool> ProcessOrderWithNotificationAsync(Order order)
    {
        // Validate inventory
        if (!_orderService.ValidateInventory(order.ProductId, order.Quantity))
        {
            _orderService.NotifyCustomer(order.CustomerEmail, "Insufficient inventory");
            return false;
        }

        // Calculate total
        var total = await _orderService.CalculateOrderTotalAsync(order.Id);
        order.Total = total;

        // Process order
        var success = await _orderService.ProcessOrderAsync(order);
        
        if (success)
        {
            _orderService.NotifyCustomer(order.CustomerEmail, $"Order confirmed. Total: ${total:F2}");
        }
        else
        {
            _orderService.NotifyCustomer(order.CustomerEmail, "Order processing failed");
        }

        return success;
    }
}

[Test]
public async Task ProcessOrderWithNotificationAsync_WhenInventoryAvailableAndProcessingSucceeds_ShouldNotifySuccess()
{
    // Arrange
    var mock = new Mock<IOrderService>();
    var processor = new OrderProcessor(mock.Object);
    
    var order = new Order 
    { 
        Id = 123, 
        ProductId = 456, 
        Quantity = 2, 
        CustomerEmail = "customer@example.com" 
    };

    var notifications = new List<string>();

    mock.Setup(x => x.ValidateInventory(456, 2))
        .Returns(true);

    mock.Setup(x => x.CalculateOrderTotalAsync(123))
        .ReturnsAsync(99.99m);

    mock.Setup(x => x.ProcessOrderAsync(order))
        .ReturnsAsync(true);

    mock.Setup(x => x.NotifyCustomer("customer@example.com", "Order confirmed. Total: $99.99"))
        .Callback((string email, string message) => notifications.Add(message));

    // Act
    var result = await processor.ProcessOrderWithNotificationAsync(order);

    // Assert
    Assert.True(result);
    Assert.Equal(99.99m, order.Total);
    
    // Verify all interactions
    mock.Verify(x => x.ValidateInventory(456, 2), Times.Once);
    mock.Verify(x => x.CalculateOrderTotalAsync(123), Times.Once);
    mock.Verify(x => x.ProcessOrderAsync(order), Times.Once);
    mock.Verify(x => x.NotifyCustomer("customer@example.com", "Order confirmed. Total: $99.99"), Times.Once);
    
    Assert.Single(notifications);
    Assert.Contains("Order confirmed", notifications[0]);
}

API Reference

It Class

Use the It class for flexible argument matching in setups:

  • It.IsAny<T>() - Matches any value of type T
  • It.Is<T>(expression) - Matches values that satisfy the given predicate

Times Class

Use the Times class to specify call count expectations:

  • Times.Never - Method should never be called
  • Times.Once - Method should be called exactly once
  • Times.AtLeastOnce - Method should be called at least once
  • Times.AtMostOnce - Method should be called at most once
  • Times.Exactly(n) - Method should be called exactly n times
  • Times.AtLeast(n) - Method should be called at least n times
  • Times.AtMost(n) - Method should be called at most n times
  • Times.Between(min, max) - Method should be called between min and max times

Setup Methods

  • Setup(expression) - Setup behavior for method calls
  • SetupGet(expression) - Setup behavior for property getters
  • SetupSet(expression) - Setup behavior for property setters
  • SetupSequence(expression) - Setup sequential behaviors for multiple calls

Behavior Methods

  • Returns(value) - Return a specific value
  • Returns(func) - Return value from function
  • ReturnsAsync(value) - Return async value (for async methods)
  • Throws<T>() - Throw exception of type T
  • Throws(exception) - Throw specific exception instance
  • Callback(action) - Execute callback when method is called
  • Callback(delegate) - Execute callback when a method is called

Limitations

  • Only supports interface and abstract class mocking (not concrete classes)
  • Requires .NET 8.0 or later

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

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

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.
  • net8.0

    • No dependencies.

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.7 79 7/29/2025
1.0.6 434 7/24/2025
1.0.5 182 7/20/2025
1.0.4 184 7/20/2025
1.0.3 109 7/16/2025
1.0.2 108 7/16/2025
1.0.1 108 7/15/2025