Skip to content

docs: describe reaching a mock's other interfaces - #855

Merged
vbreuss merged 5 commits into
mainfrom
docs/multiple-interfaces
Aug 31, 2026
Merged

docs: describe reaching a mock's other interfaces#855
vbreuss merged 5 commits into
mainfrom
docs/multiple-interfaces

Conversation

@vbreuss

@vbreuss vbreuss commented Aug 31, 2026

Copy link
Copy Markdown
Member

The "Implementing additional interfaces" section covered .Implementing<T>() and Mock.As<T>() but left out how they behave in practice. Adds:

  • the cast accessor ((ILemonadeDispenser)sut).Mock, which reaches the same surface without the As<T>() hop
  • Mock.As<T>() throwing MockException for a type the mock does not implement
  • Mock.As<TBase>() reaching a base interface member the mocked interface hides with new, which needs no .Implementing<T>() and keeps the two slots apart
  • what .Implementing<T>() does with a class that already implements the interface: members it implements non-virtually are reachable only through the interface slot
  • that .Implementing<T>() returns a new instance, that it carries the constructor parameters over, and that indexers share storage across a new

Every sample was compiled and run against the generator.

The "Implementing additional interfaces" section covered `.Implementing<T>()`
and `Mock.As<T>()` but left out how they behave in practice. Adds:

- the cast accessor `((ILemonadeDispenser)sut).Mock`, which reaches the same
  surface without the `As<T>()` hop
- `Mock.As<T>()` throwing `MockException` for a type the mock does not implement
- `Mock.As<TBase>()` reaching a base interface member the mocked interface hides
  with `new`, which needs no `.Implementing<T>()` and keeps the two slots apart
- what `.Implementing<T>()` does with a class that already implements the
  interface: members it implements non-virtually are reachable only through the
  interface slot
- that `.Implementing<T>()` returns a new instance, that it carries the
  constructor parameters over, and that indexers share storage across a `new`

Every sample was compiled and run against the generator.
@vbreuss vbreuss self-assigned this Aug 31, 2026
Copilot AI lite review requested due to automatic review settings August 31, 2026 17:11
@vbreuss vbreuss added the documentation Improvements or additions to documentation label Aug 31, 2026

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.

Pull request overview

This PR clarifies how to access and reason about a mock’s “other interface” surfaces in Mockolate, expanding the docs around .Implementing<T>() and Mock.As<T>() to better match real generator/runtime behavior.

Changes:

  • Adds examples for accessing an additional interface’s mock surface via a casted interface’s .Mock accessor (skipping the As<T>() hop).
  • Documents Mock.As<T>() error behavior when T isn’t implemented, and illustrates using As<TBase>() to reach hidden base-interface members.
  • Explains .Implementing<T>() behavior for class mocks that already implement an interface (virtual vs non-virtual members), plus notes about returning a new instance, constructor parameter reuse, and indexer behavior.
Suppressed comments (1)

Docs/pages/01-create-mocks.md:200

  • The note “Indexers are keyed by their parameter signature” is ambiguous and (taken literally) overbroad: this project has tests ensuring indexers with the same parameter types but different return/value types do not collide. The important point here is that indexer identity is not scoped by declaring interface, so base/derived indexers that only differ by new/declaring interface can share storage.
- Indexers are keyed by their parameter signature rather than by the declaring interface, so a `new` indexer and
  the base indexer it hides share the same storage.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread Docs/pages/01-create-mocks.md Outdated
@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown

Test Results

    24 files  ±0      24 suites  ±0   10m 50s ⏱️ - 2m 0s
 4 397 tests ±0   4 395 ✅ ±0  2 💤 ±0  0 ❌ ±0 
27 919 runs  ±0  27 915 ✅ ±0  4 💤 ±0  0 ❌ ±0 

Results for commit 13ea850. ± Comparison against base commit b1569f2.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown

🚀 Benchmark Results

Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
INTEL XEON PLATINUM 8573C 2.30GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
[Host] : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4

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

Event Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 232.7 ns 6.05 ns 5.65 ns 0.61 1.7 KB 1.00
Mockolate 380.7 ns 4.24 ns 3.97 ns 1.00 1.7 KB 1.00
Imposter 1,571.5 ns 4.01 ns 3.35 ns 4.13 8.8 KB 5.17
TUnitMocks 252.3 ns 1.83 ns 1.62 ns 0.66 1.34 KB 0.79
Moq 14,158.2 ns 77.57 ns 72.56 ns 37.20 12.51 KB 7.34
NSubstitute 5,449.4 ns 23.95 ns 21.23 ns 14.32 9.05 KB 5.31
FakeItEasy 124,769.8 ns 1,301.24 ns 1,086.60 ns 327.80 15.22 KB 8.94
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Intel Xeon 6973P-C 2.60GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
[Host] : .NET 10.0.11 (10.0.11, 10.0.1126.37416), 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 371.8 ns 4.33 ns 3.84 ns 1.34 1.93 KB 1.00
Mockolate 1 277.5 ns 6.11 ns 5.72 ns 1.00 1.93 KB 1.00
Imposter 1 414.4 ns 13.16 ns 12.31 ns 1.49 4.04 KB 2.09
TUnitMocks 1 392.5 ns 10.43 ns 9.75 ns 1.42 2.02 KB 1.04
Moq 1 67,570.5 ns 274.58 ns 229.29 ns 243.59 14.58 KB 7.56
NSubstitute 1 4,661.5 ns 220.33 ns 195.32 ns 16.80 9.12 KB 4.72
FakeItEasy 1 3,373.5 ns 174.39 ns 163.12 ns 12.16 8.06 KB 4.18
baseline* 10 663.2 ns 15.08 ns 14.10 ns 1.16 2.14 KB 1.00
Mockolate 10 573.0 ns 25.22 ns 22.35 ns 1.00 2.14 KB 1.00
Imposter 10 809.7 ns 12.52 ns 11.10 ns 1.42 5.52 KB 2.58
TUnitMocks 10 1,217.2 ns 26.32 ns 23.33 ns 2.13 3.73 KB 1.74
Moq 10 71,387.4 ns 3,150.54 ns 2,947.01 ns 124.76 18.46 KB 8.63
NSubstitute 10 6,674.6 ns 112.98 ns 100.16 ns 11.66 12.07 KB 5.64
FakeItEasy 10 5,749.4 ns 326.25 ns 305.17 ns 10.05 15.41 KB 7.20
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.85GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
[Host] : .NET 10.0.11 (10.0.11, 10.0.1126.37416), 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 807.4 ns 50.25 ns 47.00 ns 0.83 3.77 KB 1.00
Mockolate 1 978.5 ns 32.75 ns 30.63 ns 1.00 3.77 KB 1.00
Imposter 1 913.2 ns 28.55 ns 25.31 ns 0.93 5.16 KB 1.37
Moq 1 221,427.0 ns 1,010.83 ns 945.53 ns 226.49 20.48 KB 5.44
NSubstitute 1 10,222.3 ns 34.36 ns 26.82 ns 10.46 12.84 KB 3.41
FakeItEasy 1 11,761.2 ns 99.40 ns 92.98 ns 12.03 13.63 KB 3.62
baseline* 10 1,977.3 ns 34.29 ns 30.40 ns 0.81 4.82 KB 1.00
Mockolate 10 2,456.0 ns 18.25 ns 17.07 ns 1.00 4.82 KB 1.00
Imposter 10 2,248.2 ns 64.26 ns 60.11 ns 0.92 7.97 KB 1.65
Moq 10 232,137.7 ns 1,264.23 ns 1,182.57 ns 94.52 30 KB 6.22
NSubstitute 10 24,578.7 ns 138.38 ns 129.44 ns 10.01 25.63 KB 5.32
FakeItEasy 10 24,581.1 ns 108.27 ns 90.41 ns 10.01 32.97 KB 6.84
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 9V74 3.69GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
[Host] : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v4

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

Callback Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 355.2 ns 4.75 ns 3.97 ns 1.48 1.57 KB 1.00
Mockolate 240.7 ns 2.49 ns 2.21 ns 1.00 1.57 KB 1.00
Imposter 313.0 ns 1.33 ns 1.11 ns 1.30 2.38 KB 1.52
TUnitMocks 400.8 ns 2.05 ns 1.82 ns 1.67 1.99 KB 1.27
Moq 56,810.4 ns 478.81 ns 447.88 ns 236.09 8.88 KB 5.66
NSubstitute 3,408.8 ns 68.29 ns 63.88 ns 14.17 7.71 KB 4.91
FakeItEasy 3,603.8 ns 43.00 ns 38.12 ns 14.98 6.81 KB 4.33
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
[Host] : .NET 10.0.11 (10.0.11, 10.0.1126.37416), 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 537.7 ns 23.85 ns 22.31 ns 1.02 2.41 KB 1.00
Mockolate 1 528.0 ns 23.54 ns 22.02 ns 1.00 2.41 KB 1.00
Imposter 1 480.6 ns 12.09 ns 10.71 ns 0.91 3.13 KB 1.29
TUnitMocks 1 470.2 ns 8.32 ns 7.78 ns 0.89 1.64 KB 0.68
Moq 1 12,100.7 ns 101.55 ns 94.99 ns 22.95 10.39 KB 4.30
NSubstitute 1 7,812.1 ns 42.45 ns 37.63 ns 14.82 11.45 KB 4.74
FakeItEasy 1 8,668.5 ns 96.48 ns 85.53 ns 16.44 11.24 KB 4.66
baseline* 10 1,005.4 ns 6.34 ns 5.62 ns 0.94 2.91 KB 1.00
Mockolate 10 1,065.7 ns 8.98 ns 7.96 ns 1.00 2.91 KB 1.00
Imposter 10 1,168.7 ns 31.53 ns 29.49 ns 1.10 4.67 KB 1.61
TUnitMocks 10 1,592.8 ns 20.40 ns 19.08 ns 1.49 3.94 KB 1.35
Moq 10 19,238.6 ns 52.83 ns 46.83 ns 18.05 18.28 KB 6.29
NSubstitute 10 17,420.6 ns 150.39 ns 133.31 ns 16.35 21.08 KB 7.25
FakeItEasy 10 19,725.1 ns 63.84 ns 56.59 ns 18.51 30.81 KB 10.60
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
AMD EPYC 9V74 2.87GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.400
[Host] : .NET 10.0.11 (10.0.11, 10.0.1126.37416), X64 RyuJIT x86-64-v3

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

CreateMock Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 17.00 ns 0.124 ns 0.103 ns 0.94 160 B 1.00
Mockolate 18.02 ns 0.283 ns 0.251 ns 1.00 160 B 1.00
Imposter 279.71 ns 2.782 ns 2.602 ns 15.53 2248 B 14.05
TUnitMocks 37.29 ns 0.189 ns 0.177 ns 2.07 200 B 1.25
Moq 1,334.41 ns 5.037 ns 4.712 ns 74.08 2096 B 13.10
NSubstitute 1,827.59 ns 5.807 ns 5.432 ns 101.46 5048 B 31.55
FakeItEasy 1,778.87 ns 35.036 ns 32.773 ns 98.75 2763 B 17.27

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

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 31, 2026 18:44

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.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.

Comment thread Docs/pages/01-create-mocks.md Outdated
Comment thread Docs/pages/01-create-mocks.md Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 31, 2026 18:57
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

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.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

@sonarqubecloud

Copy link
Copy Markdown

@vbreuss
vbreuss merged commit 665863f into main Aug 31, 2026
17 checks passed
@vbreuss
vbreuss deleted the docs/multiple-interfaces branch August 31, 2026 19:07
github-actions Bot added a commit that referenced this pull request Aug 31, 2026
github-actions Bot added a commit that referenced this pull request Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants