Skip to content

feat: add a VerifyAsync overload with a cancellation token - #879

Merged
vbreuss merged 1 commit into
mainfrom
feat/verify-async-with-cancellation
Oct 9, 2026
Merged

vbreuss merged 1 commit into
mainfrom
feat/verify-async-with-cancellation

Conversation

@vbreuss

@vbreuss vbreuss commented Oct 9, 2026

Copy link
Copy Markdown
Member

An awaitable verification result returns itself from Within and WithCancellation and overwrites its timeout or token, so a caller that only wants to bound a single wait, like aweXpect.Mockolate with the token of its evaluation, could only do so by permanently replacing what the user configured on the result. As the configured token cannot be read either, there was no way to combine it with another one from the outside.

The new overload links the given token with the configured timeout and token for this call only and leaves the result unchanged.

A cancellation of the given token throws an OperationCanceledException with that token, while the configured timeout and token still throw a MockVerificationTimeoutException. This lets the caller tell its own cancellation apart from a limit configured on the result, and bound a single wait in time by canceling the given token after a delay instead of calling Within.

Adding the member to IAsyncVerificationResult is a breaking change for external implementations of the interface, which are not expected, as the only way to get one is from a VerificationResult<TVerify>.

An awaitable verification result returns itself from `Within` and `WithCancellation` and overwrites its timeout or token, so a caller that only wants to bound a single wait, like `aweXpect.Mockolate` with the token of its evaluation, could only do so by permanently replacing what the user configured on the result. As the configured token cannot be read either, there was no way to combine it with another one from the outside.

The new overload links the given token with the configured timeout and token for this call only and leaves the result unchanged.

A cancellation of the given token throws an `OperationCanceledException` with that token, while the configured timeout and token still throw a `MockVerificationTimeoutException`. This lets the caller tell its own cancellation apart from a limit configured on the result, and bound a single wait in time by canceling the given token after a delay instead of calling `Within`.

Adding the member to `IAsyncVerificationResult` is a breaking change for external implementations of the interface, which are not expected, as the only way to get one is from a `VerificationResult<TVerify>`.
@vbreuss vbreuss self-assigned this Oct 9, 2026
Copilot AI balanced review requested due to automatic review settings October 9, 2026 10:50

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

sonarqubecloud Bot commented Oct 9, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

Test Results

    24 files  ± 0      24 suites  ±0   11m 46s ⏱️ +5s
 4 529 tests + 5   4 527 ✅ + 5  2 💤 ±0  0 ❌ ±0 
28 684 runs  +35  28 680 ✅ +35  4 💤 ±0  0 ❌ ±0 

Results for commit ca43daa. ± Comparison against base commit be6f564.

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

🚀 Benchmark Results

Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.5 LTS (Noble Numbat)
AMD EPYC 9V74 3.53GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.401
[Host] : .NET 10.0.12 (10.0.12, 10.0.1226.42308), 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 380.2 ns 11.22 ns 9.95 ns 1.29 1.93 KB 1.00
Mockolate 1 295.6 ns 8.72 ns 8.15 ns 1.00 1.93 KB 1.00
Imposter 1 1,013.0 ns 14.67 ns 13.72 ns 3.43 4.04 KB 2.09
TUnitMocks 1 609.7 ns 6.91 ns 6.12 ns 2.06 2.02 KB 1.05
Moq 1 105,929.6 ns 611.51 ns 542.09 ns 358.62 14.59 KB 7.56
NSubstitute 1 4,610.7 ns 74.72 ns 69.89 ns 15.61 9.12 KB 4.72
FakeItEasy 1 4,338.5 ns 163.45 ns 152.89 ns 14.69 8.05 KB 4.17
baseline* 10 698.4 ns 14.34 ns 13.41 ns 1.22 2.14 KB 1.00
Mockolate 10 573.7 ns 8.00 ns 7.48 ns 1.00 2.14 KB 1.00
Imposter 10 976.8 ns 15.15 ns 14.17 ns 1.70 5.52 KB 2.58
TUnitMocks 10 1,372.2 ns 29.78 ns 27.86 ns 2.39 3.73 KB 1.74
Moq 10 108,426.4 ns 612.05 ns 572.51 ns 189.03 18.49 KB 8.64
NSubstitute 10 6,912.8 ns 74.39 ns 69.59 ns 12.05 12.07 KB 5.64
FakeItEasy 10 6,990.6 ns 155.32 ns 145.28 ns 12.19 15.42 KB 7.20
Details

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

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

Event Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 294.6 ns 3.92 ns 3.47 ns 0.88 1.7 KB 1.00
Mockolate 334.2 ns 15.96 ns 14.93 ns 1.00 1.7 KB 1.00
Imposter 1,548.4 ns 67.67 ns 63.30 ns 4.64 8.8 KB 5.17
TUnitMocks 228.8 ns 5.43 ns 5.08 ns 0.69 1.34 KB 0.79
Moq 16,354.4 ns 50.94 ns 39.77 ns 49.02 12.51 KB 7.35
NSubstitute 6,179.9 ns 82.08 ns 72.76 ns 18.52 9.05 KB 5.31
FakeItEasy 220,268.4 ns 1,108.16 ns 865.17 ns 660.28 15.26 KB 8.96
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.5 LTS (Noble Numbat)
Intel Xeon Platinum 8370C CPU 2.80GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.401
[Host] : .NET 10.0.12 (10.0.12, 10.0.1226.42308), X64 RyuJIT x86-64-v4

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

Callback Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 399.3 ns 6.36 ns 5.95 ns 0.89 1.57 KB 1.00
Mockolate 446.2 ns 12.54 ns 11.73 ns 1.00 1.57 KB 1.00
Imposter 576.1 ns 12.82 ns 11.99 ns 1.29 2.38 KB 1.52
TUnitMocks 707.2 ns 8.12 ns 7.60 ns 1.59 2 KB 1.27
Moq 73,208.3 ns 922.09 ns 862.52 ns 164.18 8.88 KB 5.65
NSubstitute 5,081.0 ns 47.72 ns 44.64 ns 11.40 7.71 KB 4.91
FakeItEasy 5,256.3 ns 73.91 ns 69.14 ns 11.79 6.8 KB 4.33
Details

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

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

Indexer N Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 1 1,065.5 ns 21.88 ns 20.47 ns 1.29 3.77 KB 1.00
Mockolate 1 828.4 ns 24.68 ns 23.09 ns 1.00 3.77 KB 1.00
Imposter 1 699.6 ns 22.21 ns 19.69 ns 0.85 5.16 KB 1.37
Moq 1 136,176.7 ns 1,500.23 ns 1,403.32 ns 164.50 20.39 KB 5.41
NSubstitute 1 7,528.4 ns 147.66 ns 130.90 ns 9.09 12.78 KB 3.39
FakeItEasy 1 7,770.4 ns 214.77 ns 200.90 ns 9.39 13.63 KB 3.62
baseline* 10 2,591.9 ns 12.70 ns 11.88 ns 1.36 4.82 KB 1.00
Mockolate 10 1,909.9 ns 20.90 ns 17.45 ns 1.00 4.82 KB 1.00
Imposter 10 1,734.4 ns 20.21 ns 17.92 ns 0.91 7.97 KB 1.65
Moq 10 155,708.3 ns 4,458.69 ns 4,170.66 ns 81.53 29.89 KB 6.20
NSubstitute 10 19,420.8 ns 478.18 ns 447.29 ns 10.17 25.58 KB 5.31
FakeItEasy 10 17,767.7 ns 526.11 ns 492.12 ns 9.30 32.97 KB 6.84
Details

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

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

CreateMock Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 26.17 ns 0.191 ns 0.179 ns 1.61 160 B 1.00
Mockolate 16.26 ns 0.314 ns 0.294 ns 1.00 160 B 1.00
Imposter 270.58 ns 2.740 ns 2.563 ns 16.65 2248 B 14.05
TUnitMocks 33.56 ns 0.140 ns 0.131 ns 2.06 200 B 1.25
Moq 1,340.28 ns 2.612 ns 2.315 ns 82.45 2096 B 13.10
NSubstitute 1,889.95 ns 3.165 ns 2.961 ns 116.26 5048 B 31.55
FakeItEasy 1,645.94 ns 9.719 ns 9.091 ns 101.25 2763 B 17.27
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.5 LTS (Noble Numbat)
AMD EPYC 7763 3.20GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.401
[Host] : .NET 10.0.12 (10.0.12, 10.0.1226.42308), 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 535.7 ns 11.67 ns 10.35 ns 0.96 2.41 KB 1.00
Mockolate 1 557.5 ns 14.61 ns 13.67 ns 1.00 2.41 KB 1.00
Imposter 1 483.2 ns 8.87 ns 8.30 ns 0.87 3.13 KB 1.29
TUnitMocks 1 489.3 ns 4.88 ns 4.57 ns 0.88 1.64 KB 0.68
Moq 1 12,299.7 ns 126.31 ns 118.15 ns 22.07 10.27 KB 4.25
NSubstitute 1 7,958.0 ns 43.08 ns 40.30 ns 14.28 11.45 KB 4.74
FakeItEasy 1 8,807.4 ns 66.88 ns 59.29 ns 15.81 11.24 KB 4.66
baseline* 10 1,055.9 ns 17.43 ns 16.30 ns 0.95 2.91 KB 1.00
Mockolate 10 1,115.4 ns 9.52 ns 8.91 ns 1.00 2.91 KB 1.00
Imposter 10 1,185.2 ns 9.95 ns 9.30 ns 1.06 4.67 KB 1.61
TUnitMocks 10 1,691.8 ns 10.27 ns 9.10 ns 1.52 3.94 KB 1.35
Moq 10 19,252.1 ns 70.99 ns 62.93 ns 17.26 17.03 KB 5.86
NSubstitute 10 17,643.1 ns 87.29 ns 81.65 ns 15.82 21.08 KB 7.25
FakeItEasy 10 20,767.7 ns 68.61 ns 60.82 ns 18.62 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 7dc398a into main Oct 9, 2026
18 checks passed
@vbreuss
vbreuss deleted the feat/verify-async-with-cancellation branch October 9, 2026 11:01
github-actions Bot added a commit that referenced this pull request Oct 9, 2026
… a cancellation token (#879) by Valentin Breuß
github-actions Bot added a commit that referenced this pull request Oct 9, 2026
… a cancellation token (#879) by Valentin Breuß
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

This is addressed in release v3.6.0.

@github-actions github-actions Bot added the state: released The issue is released label Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state: released The issue is released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants