Skip to content

feat: replace the MockolateUnionParameters opt-in with the MockolateDisableUnionParameters kill switch - #929

Draft
vbreuss wants to merge 2 commits into
mainfrom
feat/union-parameters-disable-switch
Draft

vbreuss wants to merge 2 commits into
mainfrom
feat/union-parameters-disable-switch

Conversation

@vbreuss

@vbreuss vbreuss commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

Now that C# 15 has shipped with .NET 11, union mode no longer needs an opt-in: it follows the project's language version on its own. The only switch left is MockolateDisableUnionParameters, which lets a project keep the classic setup and verify overloads with C# 15, e.g. to retarget to .NET 11 first and switch to the new methods later.

MockolateUnionParameters never shipped in a release, so removing it breaks no one.

The generator must still load in Roslyn 5.0, while the union tests need a Roslyn that knows C# 15. Mockolate.SourceGenerators.Tests therefore also runs on net10.0 against MinimumRoslynVersion (without the snapshot and union tests), so the classic output stays covered on the oldest supported compiler. Since net11.0 defaults to C# 15, the test projects no longer need <LangVersion>preview</LangVersion>.

Warning

Draft: the net11.0 generator tests need a Microsoft.CodeAnalysis.CSharp package with LanguageVersion.CSharp15, which is not on nuget.org yet. Until Directory.Packages.props references it, Mockolate.SourceGenerators.Tests does not compile for net11.0.

The union test job is renamed from "Union tests (net11.0, C# preview)" to "Union tests (net11.0, C# 15)".

@vbreuss vbreuss self-assigned this Nov 3, 2026
Base automatically changed from feat/union-parameters to main November 3, 2026 02:02
@vbreuss
vbreuss force-pushed the feat/union-parameters-disable-switch branch from 44eda65 to 934295d Compare November 10, 2026 19:44
@github-actions

github-actions Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

Test Results

0 files   -     44  0 suites   - 44   0s ⏱️ - 44m 2s
0 tests  -  4 643  0 ✅  -  4 643  0 💤 ±0  0 ❌ ±0 
0 runs   - 45 750  0 ✅  - 45 750  0 💤 ±0  0 ❌ ±0 

Results for commit 34d6fda. ± Comparison against base commit 130e803.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

🚀 Benchmark Results

Compared to main @​ 130e803f: memory to the latest run, time to the median of the last 10 runs, as the runners differ in speed. A relative change marks when Mockolate gets more than 15% faster or slower relative to Imposter and TUnitMocks: 🔴 / 🟢 against both of them, 🔸 / 🔹 against only one.

CallbackBenchmarks

✅ No changes in memory or relative performance (1 benchmarks)

All benchmarks compared to main
Benchmark Time Memory vs Imposter vs TUnitMocks
Callback 271.2 ns → 233.5 ns (-14%) 1,592 B → 1,592 B 0.69× → 0.66× 1.61× → 1.73×
Raw results
BenchmarkDotNet v0.15.8, Linux Ubuntu 26.04.1 LTS (Resolute Raccoon)
AMD EPYC 9V74 3.67GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 11.0.100
  [Host] : .NET 11.0.0 (11.0.0, 11.0.26.53018), X64 RyuJIT x86-64-v4

Job=InProcess  Toolchain=InProcessEmitToolchain  IterationCount=15  
LaunchCount=1  WarmupCount=10  

Callback Mean Error StdDev Ratio Allocated Alloc Ratio
Mockolate 233.5 ns 10.64 ns 9.95 ns 1.00 1592 B 1.00
Imposter 155.2 ns 2.51 ns 2.22 ns 0.67 616 B 0.39
TUnitMocks 404.7 ns 13.23 ns 12.38 ns 1.74 2056 B 1.29
Moq 60,020.0 ns 278.17 ns 232.29 ns 257.50 9063 B 5.69
NSubstitute 3,486.1 ns 95.85 ns 89.66 ns 14.96 7864 B 4.94
FakeItEasy 3,352.2 ns 115.29 ns 107.84 ns 14.38 6930 B 4.35

CompleteEventBenchmarks

✅ No changes in memory or relative performance (1 benchmarks)

All benchmarks compared to main
Benchmark Time Memory vs Imposter vs TUnitMocks
Event 201.4 ns → 209.7 ns (+4%) 1,728 B → 1,728 B 0.65× → 0.72× 0.60× → 0.57×
Raw results
BenchmarkDotNet v0.15.8, Linux Ubuntu 26.04.1 LTS (Resolute Raccoon)
AMD EPYC 9V74 3.69GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 11.0.100
  [Host] : .NET 11.0.0 (11.0.0, 11.0.26.53018), X64 RyuJIT x86-64-v4

Job=InProcess  Toolchain=InProcessEmitToolchain  IterationCount=15  
LaunchCount=1  WarmupCount=10  

Event Mean Error StdDev Ratio Allocated Alloc Ratio
Mockolate 209.7 ns 1.23 ns 1.09 ns 1.00 1728 B 1.00
Imposter 151.7 ns 0.93 ns 0.83 ns 0.72 512 B 0.30
TUnitMocks 119.7 ns 0.37 ns 0.29 ns 0.57 1392 B 0.81
Moq 10,407.8 ns 68.91 ns 57.54 ns 49.62 12761 B 7.38
NSubstitute 4,006.7 ns 14.41 ns 12.03 ns 19.10 9192 B 5.32
FakeItEasy 193,332.7 ns 460.43 ns 384.48 ns 921.81 15619 B 9.04

CompleteIndexerBenchmarks

✅ No changes in memory or relative performance (2 benchmarks)

All benchmarks compared to main
Benchmark Time Memory vs Imposter
Indexer (N=1) 818.4 ns → 967.4 ns (+18%) 3,832 B → 3,832 B 0.35× → 0.32×
Indexer (N=10) 2.35 μs → 2.49 μs (+6%) 4,912 B → 4,912 B 0.30× → 0.30×
Raw results
BenchmarkDotNet v0.15.8, Linux Ubuntu 26.04.1 LTS (Resolute Raccoon)
AMD EPYC 7763 3.23GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 11.0.100
  [Host] : .NET 11.0.0 (11.0.0, 11.0.26.53018), X64 RyuJIT x86-64-v3

Job=InProcess  Toolchain=InProcessEmitToolchain  IterationCount=15  
LaunchCount=1  WarmupCount=10  

Indexer N Mean Error StdDev Ratio Allocated Alloc Ratio
Mockolate 1 967.4 ns 24.27 ns 21.51 ns 1.00 3.74 KB 1.00
Imposter 1 311.1 ns 2.77 ns 2.45 ns 0.32 1.07 KB 0.29
Moq 1 230,947.6 ns 2,681.35 ns 2,239.05 ns 238.84 20.46 KB 5.47
NSubstitute 1 10,650.8 ns 48.39 ns 42.90 ns 11.01 12.78 KB 3.42
FakeItEasy 1 11,279.0 ns 71.01 ns 66.42 ns 11.66 13.27 KB 3.55
Mockolate 10 2,494.7 ns 52.43 ns 49.05 ns 1.00 4.8 KB 1.00
Imposter 10 753.3 ns 14.50 ns 13.56 ns 0.30 2.13 KB 0.44
Moq 10 241,357.3 ns 941.00 ns 880.21 ns 96.78 29.84 KB 6.22
NSubstitute 10 25,598.3 ns 241.61 ns 226.00 ns 10.26 25.58 KB 5.33
FakeItEasy 10 23,694.6 ns 338.35 ns 316.49 ns 9.50 32.47 KB 6.77

CompleteMethodBenchmarks

Relative performance (how many times as long the other library takes as Mockolate, main → PR)

Benchmark vs Imposter vs TUnitMocks
Method (N=1) 0.52× → 0.30× 🔴 +71% 1.30× → 0.77× 🔴 +70%
All benchmarks compared to main
Benchmark Time Memory vs Imposter vs TUnitMocks
Method (N=1) 290.1 ns → 451.8 ns (+56%) 1,936 B → 1,936 B 0.52× → 0.30× 🔴 +71% 1.30× → 0.77× 🔴 +70%
Method (N=10) 531.1 ns → 458.7 ns (-14%) 2,152 B → 2,152 B 0.56× → 0.60× 2.14× → 2.32×
Raw results
BenchmarkDotNet v0.15.8, Linux Ubuntu 26.04.1 LTS (Resolute Raccoon)
AMD EPYC 9V74 3.69GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 11.0.100
  [Host] : .NET 11.0.0 (11.0.0, 11.0.26.53018), X64 RyuJIT x86-64-v4

Job=InProcess  Toolchain=InProcessEmitToolchain  IterationCount=15  
LaunchCount=1  WarmupCount=10  

Method N Mean Error StdDev Ratio Allocated Alloc Ratio
Mockolate 1 451.8 ns 5.09 ns 4.25 ns 1.00 1936 B 1.00
Imposter 1 137.6 ns 1.28 ns 1.13 ns 0.30 728 B 0.38
TUnitMocks 1 345.7 ns 1.82 ns 1.61 ns 0.77 2088 B 1.08
Moq 1 114,005.7 ns 582.13 ns 516.04 ns 252.37 15074 B 7.79
NSubstitute 1 4,350.0 ns 60.26 ns 53.42 ns 9.63 9320 B 4.81
FakeItEasy 1 4,018.9 ns 113.54 ns 106.21 ns 8.90 8160 B 4.21
Mockolate 10 458.7 ns 5.43 ns 4.54 ns 1.00 2152 B 1.00
Imposter 10 274.5 ns 2.17 ns 1.81 ns 0.60 1088 B 0.51
TUnitMocks 10 1,063.5 ns 12.27 ns 10.87 ns 2.32 3840 B 1.78
Moq 10 117,724.1 ns 629.61 ns 558.13 ns 256.68 19065 B 8.86
NSubstitute 10 6,777.7 ns 85.72 ns 75.99 ns 14.78 12344 B 5.74
FakeItEasy 10 6,806.4 ns 76.98 ns 64.28 ns 14.84 16393 B 7.62

CompletePropertyBenchmarks

Relative performance (how many times as long the other library takes as Mockolate, main → PR)

Benchmark vs Imposter vs TUnitMocks
Property (N=1) 0.33× → 0.16× 🔴 +102% 0.85× → 0.39× 🔴 +116%
All benchmarks compared to main
Benchmark Time Memory vs Imposter vs TUnitMocks
Property (N=1) 499.8 ns → 828.9 ns (+66%) 2,432 B → 2,432 B 0.33× → 0.16× 🔴 +102% 0.85× → 0.39× 🔴 +116%
Property (N=10) 999.3 ns → 779.6 ns (-22%) 2,936 B → 2,936 B 0.33× → 0.31× 1.56× → 1.52×
Raw results
BenchmarkDotNet v0.15.8, Linux Ubuntu 26.04.1 LTS (Resolute Raccoon)
AMD EPYC 9V74 3.69GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 11.0.100
  [Host] : .NET 11.0.0 (11.0.0, 11.0.26.53018), X64 RyuJIT x86-64-v4

Job=InProcess  Toolchain=InProcessEmitToolchain  IterationCount=15  
LaunchCount=1  WarmupCount=10  

Property N Mean Error StdDev Ratio Allocated Alloc Ratio
Mockolate 1 828.9 ns 6.82 ns 6.38 ns 1.00 2432 B 1.00
Imposter 1 134.6 ns 1.18 ns 1.10 ns 0.16 672 B 0.28
TUnitMocks 1 326.9 ns 1.86 ns 1.45 ns 0.39 1696 B 0.70
Moq 1 7,500.2 ns 104.45 ns 97.70 ns 9.05 10584 B 4.35
NSubstitute 1 5,218.1 ns 29.54 ns 27.63 ns 6.30 11664 B 4.80
FakeItEasy 1 5,135.2 ns 15.61 ns 13.04 ns 6.20 11212 B 4.61
Mockolate 10 779.6 ns 7.59 ns 6.34 ns 1.00 2936 B 1.00
Imposter 10 245.5 ns 1.71 ns 1.60 ns 0.31 960 B 0.33
TUnitMocks 10 1,181.8 ns 5.63 ns 4.70 ns 1.52 4048 B 1.38
Moq 10 12,424.4 ns 79.27 ns 70.27 ns 15.94 18521 B 6.31
NSubstitute 10 12,046.6 ns 52.46 ns 46.51 ns 15.45 21529 B 7.33
FakeItEasy 10 12,527.8 ns 144.90 ns 120.99 ns 16.07 30801 B 10.49

MockCreationBenchmarks

✅ No changes in memory or relative performance (1 benchmarks)

All benchmarks compared to main
Benchmark Time Memory vs Imposter vs TUnitMocks
CreateMock 16.4 ns → 21.7 ns (+33%) 160 B → 160 B 5.55× → 5.10× 1.64× → 1.59×
Raw results
BenchmarkDotNet v0.15.8, Linux Ubuntu 26.04.1 LTS (Resolute Raccoon)
Intel Xeon Platinum 8370C CPU 2.80GHz (Max: 2.79GHz), 1 CPU, 4 logical and 2 physical cores
.NET SDK 11.0.100
  [Host] : .NET 11.0.0 (11.0.0, 11.0.26.53018), X64 RyuJIT x86-64-v4

Job=InProcess  Toolchain=InProcessEmitToolchain  IterationCount=15  
LaunchCount=1  WarmupCount=10  

CreateMock Mean Error StdDev Ratio Allocated Alloc Ratio
Mockolate 21.69 ns 0.710 ns 0.664 ns 1.00 160 B 1.00
Imposter 110.68 ns 1.295 ns 1.212 ns 5.11 504 B 3.15
TUnitMocks 34.56 ns 0.701 ns 0.656 ns 1.59 216 B 1.35
Moq 1,345.17 ns 3.946 ns 3.498 ns 62.07 2088 B 13.05
NSubstitute 1,912.41 ns 11.392 ns 10.656 ns 88.24 5032 B 31.45
FakeItEasy 1,637.73 ns 8.903 ns 7.892 ns 75.57 2764 B 17.27

vbreuss and others added 2 commits November 11, 2026 14:05
…DisableUnionParameters kill switch

Once C# 15 ships, union mode follows the language version on its own; the remaining switch only lets projects keep the classic overloads.

WIP: the generator tests need a Roslyn package with LanguageVersion.CSharp15, which is not on nuget.org yet, so this does not compile until that package is referenced. The v4 upgrade guide (Docs/changelogs/migration-to-v4.md) still describes the MockolateUnionParameters opt-in and has to move to the kill switch as well.
The generator must still load in Roslyn 5.0, so the generator tests also run against it on net10.0, while net11.0 needs a Roslyn that knows C# 15. Now that .NET 11 defaults to C# 15, the preview language version is no longer needed for the union-typed setup surface.
@vbreuss
vbreuss force-pushed the feat/union-parameters-disable-switch branch from 43a29aa to 34d6fda Compare November 11, 2026 14:26
@vbreuss vbreuss changed the title feat!: replace the MockolateUnionParameters opt-in with the MockolateDisableUnionParameters kill switch feat: replace the MockolateUnionParameters opt-in with the MockolateDisableUnionParameters kill switch Nov 11, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant