Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .claude/docs/project-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,24 @@
| `TUnit.PublicAPI` | Snapshot tests for public API |
| `TUnit.Templates.Tests` | Template instantiation tests |

## Mocking Framework

| Project | Purpose |
|---------|---------|
| `TUnit.Mocks` | Source-generated mocking framework (core runtime: `MockEngine<T>`, `Mock<T>`, setup/verification) |
| `TUnit.Mocks.SourceGenerator` | Roslyn source generator that emits mock implementations and extension methods |
| `TUnit.Mocks.SourceGenerator.Roslyn414/44/47` | Roslyn version variants (link source from base generator) |
| `TUnit.Mocks.Analyzers` | Analyzers for mock usage correctness |
| `TUnit.Mocks.Assertions` | TUnit assertion integration for mocks |
| `TUnit.Mocks.Http` | HTTP mocking (`MockHttpHandler`, `MockHttpClient`) |
| `TUnit.Mocks.Logging` | `ILogger` mocking (`MockLogger`, `MockLogger<T>`) |
| `TUnit.Mocks.Tests` | Runtime mock tests (672 tests) |
| `TUnit.Mocks.SourceGenerator.Tests` | Snapshot tests for generated code |
| `TUnit.Mocks.Analyzers.Tests` | Analyzer tests |
| `TUnit.Mocks.Http.Tests` | HTTP mock tests |
| `TUnit.Mocks.Logging.Tests` | Logging mock tests |
| `TUnit.Mocks.Benchmarks` | BenchmarkDotNet performance comparisons vs Moq/NSubstitute/FakeItEasy |

## Performance & Benchmarking

| Project | Purpose |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// <auto-generated/>
// <auto-generated/>
#nullable enable

namespace TUnit.Mocks.Generated
Expand Down Expand Up @@ -30,10 +30,13 @@ namespace TUnit.Mocks.Generated

namespace TUnit.Mocks.Generated
{
internal sealed class IReadWriter_MockImpl : global::IReadWriter, global::TUnit.Mocks.IRaisable
internal sealed class IReadWriter_MockImpl : global::IReadWriter, global::TUnit.Mocks.IRaisable, global::TUnit.Mocks.IMockObject
{
private readonly global::TUnit.Mocks.MockEngine<global::IReadWriter> _engine;

[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
global::TUnit.Mocks.IMock? global::TUnit.Mocks.IMockObject.MockWrapper { get; set; }

internal IReadWriter_MockImpl(global::TUnit.Mocks.MockEngine<global::IReadWriter> engine)
{
_engine = engine;
Expand Down Expand Up @@ -105,25 +108,26 @@ namespace TUnit.Mocks.Generated
private readonly int _memberId;
private readonly string _memberName;
private readonly global::TUnit.Mocks.Arguments.IArgumentMatcher[] _matchers;
private readonly global::System.Lazy<global::TUnit.Mocks.Setup.VoidMethodSetupBuilder> _lazyBuilder;
private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder? _builder;
private bool _builderInitialized;
private object? _builderLock;

internal IReadWriter_Write_M2_MockCall(global::TUnit.Mocks.IMockEngineAccess engine, int memberId, string memberName, global::TUnit.Mocks.Arguments.IArgumentMatcher[] matchers)
{
_engine = engine;
_memberId = memberId;
_memberName = memberName;
_matchers = matchers;
_lazyBuilder = new global::System.Lazy<global::TUnit.Mocks.Setup.VoidMethodSetupBuilder>(() =>
_ = EnsureSetup();
}

private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder EnsureSetup() =>
global::System.Threading.LazyInitializer.EnsureInitialized(ref _builder, ref _builderInitialized, ref _builderLock, () =>
{
var setup = new global::TUnit.Mocks.Setup.MethodSetup(_memberId, _matchers, _memberName);
_engine.AddSetup(setup);
return new global::TUnit.Mocks.Setup.VoidMethodSetupBuilder(setup);
}
);
_ = _lazyBuilder.Value;
}

private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder EnsureSetup() => _lazyBuilder.Value;
})!;

/// <inheritdoc />
public IReadWriter_Write_M2_MockCall Throws<TException>() where TException : global::System.Exception, new() { EnsureSetup().Throws<TException>(); return this; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// <auto-generated/>
// <auto-generated/>
#nullable enable

namespace TUnit.Mocks.Generated
Expand Down Expand Up @@ -30,10 +30,13 @@ namespace TUnit.Mocks.Generated

namespace TUnit.Mocks.Generated
{
internal sealed class IAsyncService_MockImpl : global::IAsyncService, global::TUnit.Mocks.IRaisable
internal sealed class IAsyncService_MockImpl : global::IAsyncService, global::TUnit.Mocks.IRaisable, global::TUnit.Mocks.IMockObject
{
private readonly global::TUnit.Mocks.MockEngine<global::IAsyncService> _engine;

[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
global::TUnit.Mocks.IMock? global::TUnit.Mocks.IMockObject.MockWrapper { get; set; }

internal IAsyncService_MockImpl(global::TUnit.Mocks.MockEngine<global::IAsyncService> engine)
{
_engine = engine;
Expand Down Expand Up @@ -162,24 +165,25 @@ namespace TUnit.Mocks.Generated
private readonly int _memberId;
private readonly string _memberName;
private readonly global::TUnit.Mocks.Arguments.IArgumentMatcher[] _matchers;
private readonly global::System.Lazy<global::TUnit.Mocks.Setup.MethodSetupBuilder<string>> _lazyBuilder;
private global::TUnit.Mocks.Setup.MethodSetupBuilder<string>? _builder;
private bool _builderInitialized;
private object? _builderLock;

internal IAsyncService_GetValueAsync_M0_MockCall(global::TUnit.Mocks.IMockEngineAccess engine, int memberId, string memberName, global::TUnit.Mocks.Arguments.IArgumentMatcher[] matchers)
{
_engine = engine;
_memberId = memberId;
_memberName = memberName;
_matchers = matchers;
_lazyBuilder = new global::System.Lazy<global::TUnit.Mocks.Setup.MethodSetupBuilder<string>>(() =>
}

private global::TUnit.Mocks.Setup.MethodSetupBuilder<string> EnsureSetup() =>
global::System.Threading.LazyInitializer.EnsureInitialized(ref _builder, ref _builderInitialized, ref _builderLock, () =>
{
var setup = new global::TUnit.Mocks.Setup.MethodSetup(_memberId, _matchers, _memberName);
_engine.AddSetup(setup);
return new global::TUnit.Mocks.Setup.MethodSetupBuilder<string>(setup);
}
);
}

private global::TUnit.Mocks.Setup.MethodSetupBuilder<string> EnsureSetup() => _lazyBuilder.Value;
})!;

/// <inheritdoc />
public IAsyncService_GetValueAsync_M0_MockCall Returns(string value) { EnsureSetup().Returns(value); return this; }
Expand Down Expand Up @@ -251,24 +255,25 @@ namespace TUnit.Mocks.Generated
private readonly int _memberId;
private readonly string _memberName;
private readonly global::TUnit.Mocks.Arguments.IArgumentMatcher[] _matchers;
private readonly global::System.Lazy<global::TUnit.Mocks.Setup.MethodSetupBuilder<int>> _lazyBuilder;
private global::TUnit.Mocks.Setup.MethodSetupBuilder<int>? _builder;
private bool _builderInitialized;
private object? _builderLock;

internal IAsyncService_ComputeAsync_M2_MockCall(global::TUnit.Mocks.IMockEngineAccess engine, int memberId, string memberName, global::TUnit.Mocks.Arguments.IArgumentMatcher[] matchers)
{
_engine = engine;
_memberId = memberId;
_memberName = memberName;
_matchers = matchers;
_lazyBuilder = new global::System.Lazy<global::TUnit.Mocks.Setup.MethodSetupBuilder<int>>(() =>
}

private global::TUnit.Mocks.Setup.MethodSetupBuilder<int> EnsureSetup() =>
global::System.Threading.LazyInitializer.EnsureInitialized(ref _builder, ref _builderInitialized, ref _builderLock, () =>
{
var setup = new global::TUnit.Mocks.Setup.MethodSetup(_memberId, _matchers, _memberName);
_engine.AddSetup(setup);
return new global::TUnit.Mocks.Setup.MethodSetupBuilder<int>(setup);
}
);
}

private global::TUnit.Mocks.Setup.MethodSetupBuilder<int> EnsureSetup() => _lazyBuilder.Value;
})!;

/// <inheritdoc />
public IAsyncService_ComputeAsync_M2_MockCall Returns(int value) { EnsureSetup().Returns(value); return this; }
Expand Down Expand Up @@ -340,25 +345,26 @@ namespace TUnit.Mocks.Generated
private readonly int _memberId;
private readonly string _memberName;
private readonly global::TUnit.Mocks.Arguments.IArgumentMatcher[] _matchers;
private readonly global::System.Lazy<global::TUnit.Mocks.Setup.VoidMethodSetupBuilder> _lazyBuilder;
private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder? _builder;
private bool _builderInitialized;
private object? _builderLock;

internal IAsyncService_InitializeAsync_M3_MockCall(global::TUnit.Mocks.IMockEngineAccess engine, int memberId, string memberName, global::TUnit.Mocks.Arguments.IArgumentMatcher[] matchers)
{
_engine = engine;
_memberId = memberId;
_memberName = memberName;
_matchers = matchers;
_lazyBuilder = new global::System.Lazy<global::TUnit.Mocks.Setup.VoidMethodSetupBuilder>(() =>
_ = EnsureSetup();
}

private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder EnsureSetup() =>
global::System.Threading.LazyInitializer.EnsureInitialized(ref _builder, ref _builderInitialized, ref _builderLock, () =>
{
var setup = new global::TUnit.Mocks.Setup.MethodSetup(_memberId, _matchers, _memberName);
_engine.AddSetup(setup);
return new global::TUnit.Mocks.Setup.VoidMethodSetupBuilder(setup);
}
);
_ = _lazyBuilder.Value;
}

private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder EnsureSetup() => _lazyBuilder.Value;
})!;

/// <inheritdoc />
public IAsyncService_InitializeAsync_M3_MockCall Throws<TException>() where TException : global::System.Exception, new() { EnsureSetup().Throws<TException>(); return this; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// <auto-generated/>
// <auto-generated/>
#nullable enable

namespace TUnit.Mocks.Generated
Expand Down Expand Up @@ -61,10 +61,13 @@ namespace TUnit.Mocks.Generated

namespace TUnit.Mocks.Generated
{
internal sealed class INotifier_MockImpl : global::INotifier, global::TUnit.Mocks.IRaisable
internal sealed class INotifier_MockImpl : global::INotifier, global::TUnit.Mocks.IRaisable, global::TUnit.Mocks.IMockObject
{
private readonly global::TUnit.Mocks.MockEngine<global::INotifier> _engine;

[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
global::TUnit.Mocks.IMock? global::TUnit.Mocks.IMockObject.MockWrapper { get; set; }

internal INotifier_MockImpl(global::TUnit.Mocks.MockEngine<global::INotifier> engine)
{
_engine = engine;
Expand Down Expand Up @@ -140,25 +143,26 @@ namespace TUnit.Mocks.Generated
private readonly int _memberId;
private readonly string _memberName;
private readonly global::TUnit.Mocks.Arguments.IArgumentMatcher[] _matchers;
private readonly global::System.Lazy<global::TUnit.Mocks.Setup.VoidMethodSetupBuilder> _lazyBuilder;
private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder? _builder;
private bool _builderInitialized;
private object? _builderLock;

internal INotifier_Notify_M0_MockCall(global::TUnit.Mocks.IMockEngineAccess engine, int memberId, string memberName, global::TUnit.Mocks.Arguments.IArgumentMatcher[] matchers)
{
_engine = engine;
_memberId = memberId;
_memberName = memberName;
_matchers = matchers;
_lazyBuilder = new global::System.Lazy<global::TUnit.Mocks.Setup.VoidMethodSetupBuilder>(() =>
_ = EnsureSetup();
}

private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder EnsureSetup() =>
global::System.Threading.LazyInitializer.EnsureInitialized(ref _builder, ref _builderInitialized, ref _builderLock, () =>
{
var setup = new global::TUnit.Mocks.Setup.MethodSetup(_memberId, _matchers, _memberName);
_engine.AddSetup(setup);
return new global::TUnit.Mocks.Setup.VoidMethodSetupBuilder(setup);
}
);
_ = _lazyBuilder.Value;
}

private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder EnsureSetup() => _lazyBuilder.Value;
})!;

/// <inheritdoc />
public INotifier_Notify_M0_MockCall Throws<TException>() where TException : global::System.Exception, new() { EnsureSetup().Throws<TException>(); return this; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ namespace TUnit.Mocks.Generated

namespace TUnit.Mocks.Generated
{
internal sealed class IRepository_MockImpl : global::IRepository, global::TUnit.Mocks.IRaisable
internal sealed class IRepository_MockImpl : global::IRepository, global::TUnit.Mocks.IRaisable, global::TUnit.Mocks.IMockObject
{
private readonly global::TUnit.Mocks.MockEngine<global::IRepository> _engine;

[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
global::TUnit.Mocks.IMock? global::TUnit.Mocks.IMockObject.MockWrapper { get; set; }

internal IRepository_MockImpl(global::TUnit.Mocks.MockEngine<global::IRepository> engine)
{
_engine = engine;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,13 @@ namespace TUnit.Mocks.Generated

namespace TUnit.Mocks.Generated
{
internal sealed class IMyService_MockImpl : global::TUnit.Mocks.Generated.IMyService_Mockable, global::TUnit.Mocks.IRaisable
internal sealed class IMyService_MockImpl : global::TUnit.Mocks.Generated.IMyService_Mockable, global::TUnit.Mocks.IRaisable, global::TUnit.Mocks.IMockObject
{
private readonly global::TUnit.Mocks.MockEngine<global::TUnit.Mocks.Generated.IMyService_Mockable> _engine;

[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
global::TUnit.Mocks.IMock? global::TUnit.Mocks.IMockObject.MockWrapper { get; set; }

internal IMyService_MockImpl(global::TUnit.Mocks.MockEngine<global::TUnit.Mocks.Generated.IMyService_Mockable> engine)
{
_engine = engine;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// <auto-generated/>
// <auto-generated/>
#nullable enable

namespace TUnit.Mocks.Generated
Expand Down Expand Up @@ -30,10 +30,13 @@ namespace TUnit.Mocks.Generated

namespace TUnit.Mocks.Generated
{
internal sealed class ITest_MockImpl : global::ITest, global::TUnit.Mocks.IRaisable
internal sealed class ITest_MockImpl : global::ITest, global::TUnit.Mocks.IRaisable, global::TUnit.Mocks.IMockObject
{
private readonly global::TUnit.Mocks.MockEngine<global::ITest> _engine;

[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
global::TUnit.Mocks.IMock? global::TUnit.Mocks.IMockObject.MockWrapper { get; set; }

internal ITest_MockImpl(global::TUnit.Mocks.MockEngine<global::ITest> engine)
{
_engine = engine;
Expand Down Expand Up @@ -116,25 +119,26 @@ namespace TUnit.Mocks.Generated
private readonly int _memberId;
private readonly string _memberName;
private readonly global::TUnit.Mocks.Arguments.IArgumentMatcher[] _matchers;
private readonly global::System.Lazy<global::TUnit.Mocks.Setup.VoidMethodSetupBuilder> _lazyBuilder;
private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder? _builder;
private bool _builderInitialized;
private object? _builderLock;

internal ITest_Test_M0_MockCall(global::TUnit.Mocks.IMockEngineAccess engine, int memberId, string memberName, global::TUnit.Mocks.Arguments.IArgumentMatcher[] matchers)
{
_engine = engine;
_memberId = memberId;
_memberName = memberName;
_matchers = matchers;
_lazyBuilder = new global::System.Lazy<global::TUnit.Mocks.Setup.VoidMethodSetupBuilder>(() =>
_ = EnsureSetup();
}

private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder EnsureSetup() =>
global::System.Threading.LazyInitializer.EnsureInitialized(ref _builder, ref _builderInitialized, ref _builderLock, () =>
{
var setup = new global::TUnit.Mocks.Setup.MethodSetup(_memberId, _matchers, _memberName);
_engine.AddSetup(setup);
return new global::TUnit.Mocks.Setup.VoidMethodSetupBuilder(setup);
}
);
_ = _lazyBuilder.Value;
}

private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder EnsureSetup() => _lazyBuilder.Value;
})!;

/// <inheritdoc />
public ITest_Test_M0_MockCall Throws<TException>() where TException : global::System.Exception, new() { EnsureSetup().Throws<TException>(); return this; }
Expand Down Expand Up @@ -191,24 +195,25 @@ namespace TUnit.Mocks.Generated
private readonly int _memberId;
private readonly string _memberName;
private readonly global::TUnit.Mocks.Arguments.IArgumentMatcher[] _matchers;
private readonly global::System.Lazy<global::TUnit.Mocks.Setup.MethodSetupBuilder<string>> _lazyBuilder;
private global::TUnit.Mocks.Setup.MethodSetupBuilder<string>? _builder;
private bool _builderInitialized;
private object? _builderLock;

internal ITest_Get_M1_MockCall(global::TUnit.Mocks.IMockEngineAccess engine, int memberId, string memberName, global::TUnit.Mocks.Arguments.IArgumentMatcher[] matchers)
{
_engine = engine;
_memberId = memberId;
_memberName = memberName;
_matchers = matchers;
_lazyBuilder = new global::System.Lazy<global::TUnit.Mocks.Setup.MethodSetupBuilder<string>>(() =>
}

private global::TUnit.Mocks.Setup.MethodSetupBuilder<string> EnsureSetup() =>
global::System.Threading.LazyInitializer.EnsureInitialized(ref _builder, ref _builderInitialized, ref _builderLock, () =>
{
var setup = new global::TUnit.Mocks.Setup.MethodSetup(_memberId, _matchers, _memberName);
_engine.AddSetup(setup);
return new global::TUnit.Mocks.Setup.MethodSetupBuilder<string>(setup);
}
);
}

private global::TUnit.Mocks.Setup.MethodSetupBuilder<string> EnsureSetup() => _lazyBuilder.Value;
})!;

/// <inheritdoc />
public ITest_Get_M1_MockCall Returns(string value) { EnsureSetup().Returns(value); return this; }
Expand Down
Loading
Loading