eshop-full — testing strategy
MSTest.Sdk on .NET's newer Microsoft.Testing.Platform (MTP) runner — already
pinned in global.json from the original SDK research, not a new choice. Testing isn't a
batched end-of-migration phase: every project gets its own test project in the same unit of work as
its source files — except Identity.API, whose ~129-file source tree deferred its test
project until the whole .csproj was done, since per-file coverage at that scale isn't
practical the way it is for a single-digit-to-low-teens-file project. See
Event Flow for the Decorator split this testing approach depends on.
| Project | Source files covered | Tests |
|---|---|---|
eShop.ServiceDefaults.UnitTests | 7 of 7 | 33 |
EventBusRabbitMQ.UnitTests | 7 of 7 applicable | 19 |
EventBus.UnitTests | 6 of 6 applicable | 16 |
IntegrationEventLogEF.UnitTests | 5 of 5 applicable | 17 |
Identity.API.UnitTests | 18 of 18 applicable | 101 |
| Total | 186 |
"Applicable" means a file with a real contract to guard. Pure interfaces with zero behavior of their
own (IEventBus, IEventBusBuilder) get skipped — but "simple" alone isn't the
bar: a bare enum guarding persisted DB ordinals and a single-default-value POCO both get
real tests elsewhere in this repo. Stated explicitly per file, not silently assumed clean.
Fake inner IEventBus, no broker needed
ResilientEventBusDecorator/TelemetryEventBusDecorator wrap
any IEventBus — so their tests use a fake inner bus instead of a real
RabbitMQ broker (which doesn't exist yet, no eShop.AppHost).
Proof: PublishAsync_retries_and_succeeds_after_a_transient_SocketException verifies the Polly fix end-to-end for the first time — closing a gap open since the fix landed.
Test internal classes directly, don't reflect
OpenApiOptionsExtensions is internal end-to-end. Rather than reach for
reflection (brittle, tests implementation detail) or skip coverage of logic that had already
shipped one real bug, the members got widened to internal and
<InternalsVisibleTo> added — no public API change.
Already centrally pinned (upstream's own Ordering.UnitTests uses it) — first real use in this fork.
Mock the pipeline, not the class under test
HttpClientExtensions's bearer-token-injecting handler is a private nested class —
only reachable through AddAuthToken's public surface plus a real
IServiceCollection and a mocked IAuthenticationService standing in for
the ASP.NET Core auth pipeline.
Don't mock OpenTelemetry, listen to it for real
RabbitMQTelemetryTests.cs and TelemetryEventBusDecoratorTests.cs both use
a real ActivityListener/ActivitySource to confirm the actual messaging
semantic-convention tags land with the right values — not a mock standing in for what OpenTelemetry
would do.
MTP is a genuinely different CLI surface from legacy VSTest-based dotnet test — its own
--help states plainly it "doesn't support VSTest," so the familiar
--collect:"XPlat Code Coverage"/--logger trx flags don't apply. Every flag
below was confirmed against a real scratch MSTest.Sdk project before trusting it in CI.
--coverage --coverage-output-format cobertura and --report-trx are both
built into the MTP runner itself — no extra NuGet package needed for either.
dorny/test-reporter@v3 publishes the
.trx as a PR-visible check run; a real push confirmed "3 passed, 0 failed" rendering
with each test named, end-to-end against actual GitHub Actions.
Honest gap, tracked not solved: wanted one combined HTML report across every test
project — MTP's --report-html produces one file per project instead (confirmed via a
real 2-project scratch solution). The actual fix,
microsoft/testfx#10529, merged
2026-08-09 but hasn't shipped in a Microsoft.Testing.Extensions.HtmlReport NuGet release
yet. Dependabot already tracks that package individually, so no new tooling is needed to know when
it does.