Fix InvalidOperationException in BuildServerTestHostAsync when telemetry is enabled#8553
Conversation
…try is enabled PR #8211 registered ServerTelemetry in the service provider before calling LogTestHostCreatedAsync. Because ServerTestHost's JSON-RPC message handler is only initialized inside InternalRunAsync, the build-time TestHostBuilt telemetry event attempted to flow through the not-yet-initialized server, causing ServerTestHost.AssertInitialized to throw InvalidOperationException during TestApplicationBuilder.BuildAsync(). This change moves the ReplaceService<ITelemetryCollector>(ServerTelemetry) call below LogTestHostCreatedAsync. The build-time TestHostBuilt event now goes through the originally-registered collector (NopTelemetryService), restoring previous behavior. Runtime telemetry events still flow through ServerTelemetry once the server is fully built and running. Adds a regression integration test that explicitly opts into telemetry (overriding any DOTNET_CLI_TELEMETRY_OPTOUT inherited from Arcade) and verifies the server starts without crashing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes a regression in Microsoft.Testing.Platform server-mode host construction where enabling telemetry could crash during TestApplicationBuilder.BuildAsync() by ensuring the build-time TestHostBuilt telemetry event is sent before ServerTelemetry is registered (i.e., before the JSON-RPC message handler is initialized).
Changes:
- Reorders
ServerTelemetryregistration inBuildServerTestHostAsyncto occur afterLogTestHostCreatedAsync, preventingServerTestHost.AssertInitializedfailures during build. - Adds an acceptance regression test that explicitly opts into telemetry and validates the server responds to
Initialize. - Extends server-mode test infrastructure to allow passing additional environment variables to the spawned server process.
Show a summary per file
| File | Description |
|---|---|
| test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/ServerMode/ServerModeTestsBase.cs | Adds an overload to inject additional environment variables into the server-mode test process. |
| test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/ServerLoggingTests.cs | Adds a regression test to ensure telemetry-enabled server JSON-RPC mode doesn’t crash during build. |
| src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.Modes.cs | Moves ServerTelemetry registration to after the build-time telemetry event is logged to avoid uninitialized JSON-RPC usage. |
Copilot's findings
- Files reviewed: 3/3 changed files
- Comments generated: 2
…xer assignment Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🔍 Build Failure AnalysisSummary — The build failed with Root cause: Missing using directive for EnvironmentVariableConstantsThe PR's second commit (
Affected files / errors
Proposed fix Add Build overview
All MSBuild errors (1)
Note: The error was reported twice by MSBuild (once for each project that references 🤖 Generated by the Build Failure Analysis workflow · commit 6297443
|
Evangelink
left a comment
There was a problem hiding this comment.
Generated by Build Failure Analysis for issue #8553 · ● 862.5K
Comments that could not be inline-anchored
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/ServerLoggingTests.cs:4
🔧 CS0103 — Add missing using directive for EnvironmentVariableConstants
The new test method RunningInServerJsonRpcModeWithTelemetryEnabled_DoesNotCrashDuringBuildAsync references EnvironmentVariableConstants.DOTNET_CLI_TELEMETRY_OPTOUT and EnvironmentVariableConstants.TESTINGPLATFORM_TELEMETRY_OPTOUT but the file is missing the required namespace import.
using Microsoft.Testing.Platform.Helpers;
using Microsoft.Testing.Platform.ServerMode.IntegrationTests.Messages.V…
</details>
<details><summary>test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/ServerMode/ServerModeTestsBase.cs:7</summary>
🔧 **CS0103** — Add missing using directive for `EnvironmentVariableConstants`
This file now references `EnvironmentVariableConstants.TESTINGPLATFORM_EXIT_PROCESS_ON_UNHANDLED_EXCEPTION` on line 44 but is missing the required namespace import.
```suggestion
using Microsoft.Testing.Platform.Acceptance.IntegrationTests;
using Microsoft.Testing.Platform.Helpers;
using Microsoft.Testing.Platform.ServerMode.IntegrationTests.Messages.V100;
…dd using ServerModeTestsBase.cs (shared with MSTest.Acceptance.IntegrationTests via Compile Include) now references EnvironmentVariableConstants. That project did not embed EnvironmentVariableConstants.cs nor declare a global using for Microsoft.Testing.Platform.Helpers, so the build failed with CS0103 under net11.0. Add the Compile Include and an explicit using directive to the shared file. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The original comments implied NopTelemetryService was always the collector active at LogTestHostCreatedAsync, but when telemetry is opted in, TelemetryManager.BuildTelemetryAsync registers a real collector via the user-supplied _telemetryFactory. Reword both the pre- and post-LogTestHostCreatedAsync comments to refer to `the collector previously registered by TelemetryManager in SetupCommonServicesAsync` so the rationale stays accurate in both enabled and disabled telemetry scenarios. Addresses Copilot review feedback on #8553. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Regression
PR #8211 registered
ServerTelemetryin the service provider before callingLogTestHostCreatedAsyncinsideBuildServerTestHostAsync. BecauseServerTestHost's JSON-RPC message handler (_messageHandler) is only initialized insideInternalRunAsync, the build-timeTestHostBuilttelemetry event attempted to flow through the not-yet-initialized server, causingServerTestHost.AssertInitializedto throwInvalidOperationExceptionduringTestApplicationBuilder.BuildAsync().Reported during dogfood of MTP in the Coverage repo:
The bug does not reproduce in CI because Arcade sets
DOTNET_CLI_TELEMETRY_OPTOUT=1on the test process, which causesLogTestHostCreatedAsyncto early-return before reachingServerTelemetry.Fix
Move the
ReplaceService<ITelemetryCollector>(ServerTelemetry)call belowLogTestHostCreatedAsync. The build-timeTestHostBuiltevent now goes through the originally-registered collector (typicallyNopTelemetryService), restoring the pre-#8211 behavior for that single event. Runtime telemetry events still flow throughServerTelemetryonce the server is fully built and running.Regression test
Added
ServerLoggingTests.RunningInServerJsonRpcModeWithTelemetryEnabled_DoesNotCrashDuringBuildAsyncwhich explicitly opts into telemetry (setsDOTNET_CLI_TELEMETRY_OPTOUT=0andTESTINGPLATFORM_TELEMETRY_OPTOUT=0to override any inherited opt-out) and verifies the server boots and responds toInitialize. Without the fix, this test fails with the exact stack trace above; with the fix, it passes.Also extended
ServerModeTestsBase.StartAsServerAndConnectToTheClientAsyncwith an overload accepting additional environment variables.Validation
main.Microsoft.Testing.Platform.UnitTeststests pass acrossnet462/net8.0/net9.0.ServerLoggingTestspass.