NSubstituteConcrete 1.0.7
dotnet add package NSubstituteConcrete --version 1.0.7
NuGet\Install-Package NSubstituteConcrete -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="NSubstituteConcrete" Version="1.0.7" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="NSubstituteConcrete" Version="1.0.7" />
<PackageReference Include="NSubstituteConcrete" />
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 NSubstituteConcrete --version 1.0.7
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: NSubstituteConcrete, 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 NSubstituteConcrete@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=NSubstituteConcrete&version=1.0.7
#tool nuget:?package=NSubstituteConcrete&version=1.0.7
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
NSubstituteConcrete
A .NET library that extends NSubstitute to support mocking concrete classes and static methods using Harmony runtime patching.
Features
- Concrete class mocking: Mock non-virtual methods in concrete classes
- Static method mocking: Mock static methods with familiar NSubstitute syntax
- Harmony-powered: Uses Harmony library for runtime IL patching
- NSubstitute syntax: Familiar API for existing NSubstitute users
- Zero configuration: Works with existing concrete classes without modification
Installation
dotnet add package NSubstituteConcrete
Usage
Concrete Class Mocking
using NSubstituteConcrete;
public class UserService
{
public string GetUserName(int id) => $"User{id}";
public void SaveUser(User user) { /* implementation */ }
}
// Create substitute
var userService = NSubstituteExtensions.ForConcrete<UserService>();
// Setup methods
userService.Setup(x => x.GetUserName(1)).Returns("John Doe");
userService.Setup(x => x.SaveUser(It.IsAny<User>()))
.Callback(() => Console.WriteLine("User saved"));
// Verify calls
userService.Verify(x => x.GetUserName(1), times: 1);
// Cleanup when done
userService.Cleanup();
Static Method Mocking
using NSubstitute.Concrete;
public static class FileHelper
{
public static string ReadFile(string path) => File.ReadAllText(path);
public static void DeleteFile(string path) => File.Delete(path);
}
// Setup static methods
Static.Setup(() => FileHelper.ReadFile("test.txt")).Returns("mock content");
Static.Setup(() => FileHelper.DeleteFile(It.IsAny<string>()))
.Callback(() => Console.WriteLine("File deleted"));
// Use normally
string content = FileHelper.ReadFile("test.txt"); // Returns "mock content"
// Verify calls
Static.Verify(() => FileHelper.ReadFile("test.txt"), times: 1);
// Cleanup
Static.ClearAll();
Async Methods
var service = NSubstituteExtensions.ForConcrete<AsyncService>();
// Async methods with return values
service.SetupAsync(x => x.GetDataAsync(1)).Returns("result");
// Async void methods
service.SetupAsync(x => x.ProcessAsync())
.Callback(() => Console.WriteLine("Processing"));
// Static async methods
Static.SetupAsync(() => HttpClient.GetAsync("url")).Returns("response");
// Cleanup
service.Cleanup();
Properties
var service = NSubstituteExtensions.ForConcrete<ConfigService>();
// Setup property getters
service.SetupProperty(x => x.ConnectionString).Returns("test-connection");
// Set property values directly
service.SetProperty(x => x.Timeout, TimeSpan.FromSeconds(30));
// Cleanup
service.Cleanup();
Comparison with Other Testing Libraries
Feature | NSubstituteConcrete | Standard NSubstitute | Moq | TypeMock Isolator | Microsoft Fakes |
---|---|---|---|---|---|
Concrete classes | ✅ All methods | ❌ Virtual only | ❌ Virtual only | ✅ All methods | ✅ All methods |
Static methods | ✅ Full support | ❌ Not supported | ❌ Not supported | ✅ Full support | ✅ Full support |
Non-virtual methods | ✅ Supported | ❌ Not supported | ❌ Not supported | ✅ Supported | ✅ Supported |
Sealed classes | ✅ Supported | ❌ Not supported | ❌ Not supported | ✅ Supported | ✅ Supported |
Cost | 🆓 FREE | 🆓 Free | 🆓 Free | 💰 ~$1,000+/license | 💰 VS Enterprise required |
Performance | ⚡ Fast | ⚡ Fast | ⚡ Fast | ⚠️ Slower (profiler) | ⚠️ Slower (shims) |
Setup complexity | ✅ Simple | ✅ Simple | ✅ Simple | ⚠️ Complex setup | ⚠️ Complex setup |
Syntax familiarity | ✅ NSubstitute | ✅ NSubstitute | ❌ Different | ❌ Different | ❌ Different |
Cleanup
Test Cleanup
public class MyTests : IDisposable
{
public void Dispose()
{
// Clean up all substitutes and static patches
ConcreteCleanupExtensions.ClearAll();
}
}
Individual Cleanup
// Clean up specific substitute
substitute.Cleanup();
// Clean up only static method patches
Static.ClearAll();
Limitations
- Method inlining: Aggressively optimized methods may be inlined and cannot be patched
- Generic methods: Generic method patches may affect all type instantiations
- Native methods: P/Invoke and external methods cannot be patched
- Static constructors: May run at unexpected times during patching
Requirements
- .NET 6.0 or later
- Compatible with .NET Framework 4.8+ via .NET Standard 2.0
Dependencies
- NSubstitute - Base mocking library
- Lib.Harmony - Runtime IL patching
Building
git clone https://github.com/jayarrowz/NSubstituteConcrete.git
cd NSubstitute.Concrete
dotnet restore
dotnet build
dotnet test
Project Structure
NSubstitute.Concrete/
├── Core/ # Core infrastructure
├── Static/ # Static method support
├── Setup/ # Method setup classes
├── Utilities/ # Helper classes
└── Cleanup/ # Cleanup and diagnostics
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Please ensure tests pass and add tests for new functionality.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- NSubstitute - Inspiration and base API design
- Harmony - Runtime patching capabilities
Related Projects
- NSubstitute - Original mocking library
- Moq - Alternative mocking framework
- Pose - Alternative method replacement library
Product | Versions 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 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
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.
-
.NETStandard 2.0
- Lib.Harmony (>= 2.3.6)
- NSubstitute (>= 5.3.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
See https://github.com/JayArrowz/NSubstituteConcrete/releases for release notes.