Skip to content

refactor: migrate the remaining classic extension methods to extension blocks - #905

Merged
vbreuss merged 1 commit into
mainfrom
refactor/extension-blocks
Oct 18, 2026
Merged

vbreuss merged 1 commit into
mainfrom
refactor/extension-blocks

Conversation

@vbreuss

@vbreuss vbreuss commented Oct 18, 2026

Copy link
Copy Markdown
Member

ParameterExtensions, ReturnsThrowsAsyncExtensions and CallbacksExtensions were the last public files that still used classic this extension methods, so the source and the API snapshots mixed two styles.

  • Not breaking: the lowered metadata signatures (names, generic parameter order and constraints, parameter types, defaults, [CallerArgumentExpression]) are identical on all target frameworks, and test assemblies compiled against main pass against the new library, including already generated mocks that call CallbacksExtensions.Register<T>.
  • Explicit type arguments in extension form (setup.ReturnsAsync<int>(5)) still compile; they bind to the block's type parameters.
  • The generated ReturnsThrowsAsyncExtensions2 for higher arities stays classic.

…n blocks

`ParameterExtensions`, `ReturnsThrowsAsyncExtensions` and `CallbacksExtensions` were the last public files that still used classic `this` extension methods, so the source and the API snapshots mixed two styles.

- Not breaking: the lowered metadata signatures (names, generic parameter order and constraints, parameter types, defaults, `[CallerArgumentExpression]`) are identical on all target frameworks, and test assemblies compiled against main pass against the new library, including already generated mocks that call `CallbacksExtensions.Register<T>`.
- Explicit type arguments in extension form (`setup.ReturnsAsync<int>(5)`) still compile; they bind to the block's type parameters.
- The generated `ReturnsThrowsAsyncExtensions2` for higher arities stays classic.
@vbreuss vbreuss self-assigned this Oct 18, 2026
Copilot AI balanced review requested due to automatic review settings October 18, 2026 17:27

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown

Test Results

    24 files      24 suites   28m 5s ⏱️
 4 514 tests  4 514 ✅ 0 💤 0 ❌
28 680 runs  28 680 ✅ 0 💤 0 ❌

Results for commit cf2231a.

@github-actions

Copy link
Copy Markdown

👽 Mutation Results

Mutation testing badge

Mockolate

Details
File Score Killed Survived Timeout No Coverage Ignored Compile Errors Runtime Errors Total Detected Total Undetected Total Mutants
ParameterExtensions.cs 70.00% 63 27 0 0 22 2 0 63 27 114
Setup/CallbacksExtensions.cs 100.00% 3 0 0 0 1 0 0 3 0 4

The final mutation score is 70.97%

Coverage Thresholds: high:80 low:60 break:0

@github-actions

Copy link
Copy Markdown

🚀 Benchmark Results

Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.5 LTS (Noble Numbat)
AMD EPYC 9V74 3.49GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.303
[Host] : .NET 10.0.13 (10.0.13, 10.0.1326.50504), X64 RyuJIT x86-64-v4

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

Method N Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 1 377.9 ns 10.49 ns 9.81 ns 1.38 1.93 KB 1.00
Mockolate 1 274.5 ns 2.01 ns 1.78 ns 1.00 1.93 KB 1.00
Imposter 1 409.0 ns 2.22 ns 1.97 ns 1.49 3.96 KB 2.05
TUnitMocks 1 391.9 ns 2.89 ns 2.70 ns 1.43 2.02 KB 1.05
Moq 1 104,386.9 ns 728.68 ns 645.96 ns 380.35 14.59 KB 7.56
NSubstitute 1 4,557.4 ns 17.81 ns 15.78 ns 16.61 9.12 KB 4.72
FakeItEasy 1 4,564.5 ns 29.18 ns 27.30 ns 16.63 8.05 KB 4.17
baseline* 10 684.1 ns 19.95 ns 18.66 ns 1.40 2.14 KB 1.00
Mockolate 10 487.0 ns 3.79 ns 3.54 ns 1.00 2.14 KB 1.00
Imposter 10 694.9 ns 11.11 ns 10.39 ns 1.43 4.8 KB 2.24
TUnitMocks 10 1,154.8 ns 10.50 ns 9.82 ns 2.37 3.73 KB 1.74
Moq 10 107,745.2 ns 613.86 ns 544.17 ns 221.27 18.49 KB 8.64
NSubstitute 10 6,566.1 ns 125.46 ns 117.36 ns 13.48 12.07 KB 5.64
FakeItEasy 10 7,042.0 ns 106.81 ns 94.69 ns 14.46 15.42 KB 7.20
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.5 LTS (Noble Numbat)
AMD EPYC 7763 3.23GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.303
[Host] : .NET 10.0.13 (10.0.13, 10.0.1326.50504), X64 RyuJIT x86-64-v3

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

Event Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 169.63 ns 4.339 ns 4.059 ns 0.53 1.7 KB 1.00
Mockolate 320.7 ns 13.71 ns 12.83 ns 1.00 1.7 KB 1.00
Imposter 972.3 ns 20.58 ns 17.18 ns 3.04 7.18 KB 4.22
TUnitMocks 189.1 ns 2.74 ns 2.29 ns 0.59 1.34 KB 0.79
Moq 16,620.7 ns 74.60 ns 69.78 ns 51.90 12.73 KB 7.47
NSubstitute 6,161.8 ns 67.42 ns 63.07 ns 19.24 9.05 KB 5.31
FakeItEasy 222,445.9 ns 1,906.24 ns 1,783.10 ns 694.60 15.26 KB 8.96
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.5 LTS (Noble Numbat)
AMD EPYC 7763 2.60GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.303
[Host] : .NET 10.0.13 (10.0.13, 10.0.1326.50504), X64 RyuJIT x86-64-v3

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

Callback Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 215.7 ns 5.42 ns 4.81 ns 0.67 1.57 KB 1.00
Mockolate 320.7 ns 8.23 ns 7.70 ns 1.00 1.57 KB 1.00
Imposter 433.0 ns 6.13 ns 5.73 ns 1.35 2.37 KB 1.51
TUnitMocks 503.1 ns 6.68 ns 5.92 ns 1.57 2 KB 1.27
Moq 99,362.8 ns 627.95 ns 587.39 ns 310.01 8.88 KB 5.66
NSubstitute 4,754.8 ns 24.80 ns 20.71 ns 14.84 7.71 KB 4.91
FakeItEasy 4,863.0 ns 19.90 ns 17.64 ns 15.17 6.81 KB 4.33
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.5 LTS (Noble Numbat)
AMD EPYC 7763 3.14GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.303
[Host] : .NET 10.0.13 (10.0.13, 10.0.1326.50504), X64 RyuJIT x86-64-v3

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

Indexer N Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 1 921.1 ns 22.93 ns 21.44 ns 0.92 3.77 KB 1.00
Mockolate 1 997.5 ns 46.28 ns 43.29 ns 1.00 3.77 KB 1.00
Imposter 1 829.1 ns 12.88 ns 12.04 ns 0.83 4.99 KB 1.33
Moq 1 219,140.4 ns 1,128.93 ns 1,000.77 ns 220.08 20.37 KB 5.41
NSubstitute 1 10,634.0 ns 49.74 ns 46.53 ns 10.68 12.84 KB 3.41
FakeItEasy 1 12,293.9 ns 52.80 ns 46.80 ns 12.35 13.63 KB 3.62
baseline* 10 2,396.3 ns 12.49 ns 11.68 ns 0.95 4.82 KB 1.00
Mockolate 10 2,533.5 ns 11.13 ns 9.86 ns 1.00 4.82 KB 1.00
Imposter 10 1,556.0 ns 40.96 ns 38.31 ns 0.61 6.47 KB 1.34
Moq 10 232,959.9 ns 1,003.24 ns 938.43 ns 91.95 29.89 KB 6.20
NSubstitute 10 25,956.6 ns 88.00 ns 78.01 ns 10.25 25.63 KB 5.32
FakeItEasy 10 25,390.7 ns 368.83 ns 326.96 ns 10.02 32.97 KB 6.84
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.5 LTS (Noble Numbat)
AMD EPYC 7763 2.73GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.303
[Host] : .NET 10.0.13 (10.0.13, 10.0.1326.50504), X64 RyuJIT x86-64-v3

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

CreateMock Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 20.91 ns 1.009 ns 0.944 ns 1.14 160 B 1.00
Mockolate 18.40 ns 0.455 ns 0.426 ns 1.00 160 B 1.00
Imposter 280.99 ns 5.126 ns 4.544 ns 15.28 2240 B 14.00
TUnitMocks 37.52 ns 0.941 ns 0.880 ns 2.04 200 B 1.25
Moq 1,439.41 ns 11.153 ns 10.432 ns 78.26 2096 B 13.10
NSubstitute 1,956.47 ns 31.335 ns 29.311 ns 106.38 5048 B 31.55
FakeItEasy 1,810.31 ns 24.203 ns 22.640 ns 98.43 2763 B 17.27
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.5 LTS (Noble Numbat)
AMD EPYC 7763 3.24GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.303
[Host] : .NET 10.0.13 (10.0.13, 10.0.1326.50504), X64 RyuJIT x86-64-v3

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

Property N Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 1 593.3 ns 11.87 ns 11.10 ns 1.14 2.41 KB 1.00
Mockolate 1 522.1 ns 22.02 ns 20.60 ns 1.00 2.41 KB 1.00
Imposter 1 406.6 ns 2.38 ns 1.99 ns 0.78 2.98 KB 1.23
TUnitMocks 1 454.5 ns 4.28 ns 4.00 ns 0.87 1.64 KB 0.68
Moq 1 11,889.9 ns 80.24 ns 71.13 ns 22.80 10.39 KB 4.30
NSubstitute 1 7,917.8 ns 72.79 ns 68.09 ns 15.19 11.45 KB 4.74
FakeItEasy 1 8,353.8 ns 42.61 ns 37.78 ns 16.02 11.24 KB 4.66
baseline* 10 959.2 ns 15.07 ns 14.09 ns 0.91 2.91 KB 1.00
Mockolate 10 1,057.7 ns 17.84 ns 15.82 ns 1.00 2.91 KB 1.00
Imposter 10 636.5 ns 3.22 ns 2.86 ns 0.60 3.26 KB 1.12
TUnitMocks 10 1,566.2 ns 6.65 ns 6.22 ns 1.48 3.94 KB 1.35
Moq 10 18,734.6 ns 97.29 ns 81.24 ns 17.72 18.28 KB 6.29
NSubstitute 10 17,588.4 ns 59.52 ns 52.77 ns 16.63 21.08 KB 7.25
FakeItEasy 10 19,478.7 ns 50.86 ns 47.58 ns 18.42 30.81 KB 10.60

baseline* rows show the corresponding Mockolate benchmark from the most recent successful main branch build with results, for regression comparison.

@vbreuss
vbreuss merged commit e9b7e8a into main Oct 18, 2026
18 checks passed
@vbreuss
vbreuss deleted the refactor/extension-blocks branch October 18, 2026 23:10
github-actions Bot added a commit that referenced this pull request Oct 19, 2026
… extension methods to extension blocks (#905) by Valentin Breuß
github-actions Bot added a commit that referenced this pull request Oct 19, 2026
… extension methods to extension blocks (#905) by Valentin Breuß
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.

2 participants