SMock 2.6.0

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

🎯 SMock - Static & Instance Method Mocking for .NET

<div align="center">

NuGet Version NuGet Downloads GitHub Stars License .NET Version

A mocking library that makes testing static methods easier!

</div>


Why SMock?

SMock breaks down the barriers of testing legacy code, third-party dependencies, and static APIs. Built on MonoMod runtime modification technology, SMock gives you the power to mock what others can't.

  • Mock Static Methods: The only .NET library that handles static methods seamlessly
  • Two API Styles: Choose Hierarchical (with validation) or Sequential (disposable) patterns
  • Zero Configuration: Works with your existing test frameworks (NUnit, xUnit, MSTest)
  • Complete Feature Set: Async/await, parameter matching, callbacks, exceptions, unsafe code

Installation

Package Manager

Install-Package SMock

.NET CLI

dotnet add package SMock

💡 Pro Tip: SMock works great with any testing framework - NUnit, xUnit, MSTest, you name it!


🚀 Quick Start

// Mock a static method in just one line - Sequential API
using var mock = Mock.Setup(() => File.ReadAllText("config.json"))
    .Returns("{ \"setting\": \"test\" }");

// Your code now uses the mocked value!
var content = File.ReadAllText("config.json"); // Returns test JSON

// Or use the Hierarchical API with inline validation
Mock.Setup(() => DateTime.Now, () =>
{
    var result = DateTime.Now;
    Assert.AreEqual(new DateTime(2024, 1, 1), result);
}).Returns(new DateTime(2024, 1, 1));

Core Concepts

Hook-Based Runtime Modification

SMock uses MonoMod to create runtime hooks that intercept method calls:

  • Non-Invasive: No source code changes required
  • Isolated: Each test runs in isolation
  • Fast: Minimal performance overhead
  • Auto-Cleanup: Hooks automatically removed after test completion

Mock Lifecycle

// 1. Setup: Create a mock for the target method
var mock = Mock.Setup(() => DateTime.Now);

// 2. Configure: Define return values or behaviors
mock.Returns(new DateTime(2024, 1, 1));

// 3. Execute: Run your code - calls are intercepted
var now = DateTime.Now; // Returns mocked value

// 4. Cleanup: Dispose mock (Sequential) or automatic (Hierarchical)
mock.Dispose(); // Or automatic with 'using'

API Styles

SMock provides two distinct API patterns to fit different testing preferences:

Sequential API

Perfect for clean, scoped mocking with automatic cleanup:

[Test]
public void TestFileOperations()
{
    // Mock file existence check
    using var existsMock = Mock.Setup(() => File.Exists("test.txt"))
        .Returns(true);

    // Mock file content reading
    using var readMock = Mock.Setup(() => File.ReadAllText("test.txt"))
        .Returns("Hello World");

    // Your code under test
    var processor = new FileProcessor();
    var result = processor.ProcessFile("test.txt");

    Assert.AreEqual("HELLO WORLD", result);
} // Mocks automatically cleaned up here

Hierarchical API

Perfect for inline validation during mock execution:

[Test]
public void TestDatabaseConnection()
{
    var expectedConnectionString = "Server=localhost;Database=test;";

    Mock.Setup(() => DatabaseConnection.Connect(It.IsAny<string>()), () =>
    {
        // This validation runs DURING the mock execution
        var actualCall = DatabaseConnection.Connect(expectedConnectionString);
        Assert.IsNotNull(actualCall);
        Assert.IsTrue(actualCall.IsConnected);
    }).Returns(new MockConnection { IsConnected = true });

    // Test your service
    var service = new DatabaseService();
    service.InitializeConnection(expectedConnectionString);
}

⚡ Performance

SMock is designed for minimal performance impact:

  • Runtime Hooks: Only active during tests
  • Zero Production Overhead: No dependencies in production builds
  • Efficient Interception: Built on MonoMod's optimized IL modification
  • Benchmarked: Comprehensive performance testing with BenchmarkDotNet

Performance Characteristics

Operation Overhead Notes
Mock Setup ~1-2ms One-time cost per mock
Method Interception <0.1ms Minimal runtime impact
Cleanup <1ms Automatic hook removal
Memory Usage Minimal Temporary IL modifications only

⚠️ Known Issues & Solutions

Compiler Optimization Issue

If your mocks are not being applied and you're getting the original method behavior instead of the mocked behavior, this is likely due to compiler optimizations. The compiler may inline or optimize method calls, preventing SMock from intercepting them.

Solutions:

  1. Run tests in Debug configuration:

    dotnet test --configuration Debug
    
  2. Disable compiler optimization in your test project by adding this to your .csproj:

    <PropertyGroup>
      <Optimize>false</Optimize>
    </PropertyGroup>
    
  3. Disable optimization for specific methods using the MethodImpl attribute:

    [Test]
    [MethodImpl(MethodImplOptions.NoOptimization)]
    public void MyTestMethod()
    {
        using var mock = Mock.Setup(() => File.ReadAllText("config.json"))
            .Returns("{ \"setting\": \"test\" }");
    
        // Your test code here
    }
    

This issue typically occurs in Release builds where the compiler aggressively optimizes method calls. Using any of the above solutions will ensure your mocks work correctly.


Additional Resources


📄 License

This library is available under the MIT license.


<div align="center">

🚀 Ready to revolutionize your .NET testing?

⚡ Get Started Now | 📚 View Examples | 💬 Join Discussion


Made with ❤️ by @SvetlovA and the SMock community

</div>

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 is compatible.  net463 was computed.  net47 is compatible.  net471 is compatible.  net472 is compatible.  net48 is compatible.  net481 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos 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
2.6.0 255 11/27/2025
2.5.0 2,366 8/18/2025
2.4.0 1,757 3/21/2025
2.3.0 2,245 11/20/2024
2.2.0 19,565 2/8/2024
2.1.0 130,122 8/29/2023
2.0.0 351 7/16/2023
1.8.0 967 12/13/2022
1.7.1 2,143 8/27/2022
1.7.0 602 8/27/2022
1.6.0 755 12/21/2021
1.5.0 522 8/2/2021
1.4.0 521 7/18/2021
1.3.0 516 7/1/2021
1.2.1 517 5/17/2021
1.2.0 577 5/5/2021
1.1.0 512 4/30/2021
1.0.0 601 4/27/2021