TUnit.Mocks
TUnit.Mocks is a standalone, source-generated, AOT-compatible mocking framework. Because mocks are generated at compile time, it works with Native AOT, trimming, and single-file publishing — unlike traditional mocking libraries that rely on runtime proxy generation.
While it integrates seamlessly with TUnit's assertion engine, TUnit.Mocks has no dependency on the TUnit test framework and works with any test runner — xUnit, NUnit, MSTest, or no framework at all.
TUnit.Mocks is currently in beta. The API may change before the stable release.
Installation
Add the NuGet package to your test project:
dotnet add package TUnit.Mocks --prerelease
For HTTP mocking or logging helpers, also add:
dotnet add package TUnit.Mocks.Http --prerelease
dotnet add package TUnit.Mocks.Logging --prerelease
TUnit.Mocks requires C# 14 or later (LangVersion set to 14 or preview). If your project targets an older version, you will see error TM004 at compile time.
Your First Mock
using TUnit.Mocks;
public interface IGreeter
{
string Greet(string name);
}
public class GreeterTests
{
[Test]
public async Task Greet_Returns_Configured_Value()
{
// Arrange — create a mock
var mock = Mock.Of<IGreeter>();
// Configure — set up a return value
mock.Greet(Any()).Returns("Hello!");
// Act — use the mock object
IGreeter greeter = mock.Object;
var result = greeter.Greet("Alice");
// Assert — verify the result and the call
await Assert.That(result).IsEqualTo("Hello!");
mock.Greet("Alice").WasCalled(Times.Once);
}
}
Key Concepts
Creating Mocks
| Factory Method | Use Case |
|---|---|
Mock.Of<T>() | Mock an interface or abstract class |
Mock.OfPartial<T>(args) | Mock a concrete class (calls base for unconfigured methods) |
Mock.OfDelegate<T>() | Mock a delegate (Func<>, Action<>, etc.) |
Mock.Wrap<T>(instance) | Wrap a real object with selective overrides |
Mock.Of<T1, T2>() | Mock multiple interfaces on a single object |
Mock.HttpHandler() | Create a MockHttpHandler (requires TUnit.Mocks.Http) |
Mock.HttpClient(baseAddress?) | Create a MockHttpClient — an HttpClient with a .Handler property (requires TUnit.Mocks.Http) |
Mock.Logger() | Create a MockLogger (requires TUnit.Mocks.Logging) |
Mock.Logger<T>() | Create a MockLogger<T> implementing ILogger<T> (requires TUnit.Mocks.Logging) |
All factory methods accept an optional MockBehavior parameter:
var loose = Mock.Of<IService>(); // loose (default)
var strict = Mock.Of<IService>(MockBehavior.Strict); // throws on unconfigured calls
The Mock Wrapper
Mock.Of<T>() returns a Mock<T> wrapper. Extension methods are generated directly on Mock<T> for each member of the mocked type, and the chain methods (.Returns(), .WasCalled(), etc.) disambiguate between setup and verification:
var mock = Mock.Of<IService>();
mock.GetUser(Any()).Returns(user); // setup — .Returns() makes it a stub
mock.GetUser(42).WasCalled(Times.Once); // verify — .WasCalled() makes it a check
mock.RaiseOnMessage("hi"); // raise events — Raise{EventName}()
mock.Object // the T instance to pass to your code under test
Implicit Conversion
You can pass Mock<T> directly where T is expected — no .Object needed:
var mock = Mock.Of<IGreeter>();
IGreeter greeter = mock; // implicit conversion
Loose vs Strict Mode
| Mode | Unconfigured methods | Default |
|---|---|---|
MockBehavior.Loose | Return smart defaults (0, "", false, null, auto-mocked interfaces) | Yes |
MockBehavior.Strict | Throw MockStrictBehaviorException | No |
Concise Argument Matching
TUnit.Mocks imports matchers globally — no Arg. prefix needed. Raw values, inline lambdas, and Any() work directly as arguments:
var mock = Mock.Of<IUserService>();
// Any() — matches everything
mock.GetUser(Any()).Returns(user);
// Raw values — implicit exact matching
mock.GetUser(42).Returns(alice);
// Inline lambdas — predicate matching directly in the call
mock.GetUser(id => id > 0).Returns(validUser);
mock.GetByRole(role => role == "admin").Returns(admins);
// Mix lambdas with Any() or raw values
mock.Search(name => name.StartsWith("A"), Any()).Returns(results);
// Is<T>() — explicit predicate matching (also works)
mock.GetUser(Is<int>(id => id > 0)).Returns(validUser);
See Argument Matchers for the full API.
What's Next
- Setup & Stubbing — configure return values, callbacks, exceptions, and property behaviors
- Verification — verify calls, ordering, and assertion integration
- Argument Matchers — match arguments with predicates, patterns, and capture values
- Advanced Features — state machines, events, auto-mocking, diagnostics, and more
- HTTP Mocking — mock
HttpClientwithMockHttpHandler - Logging — capture and verify
ILoggercalls withMockLogger