[fix] Add filesystem integration tests for DotnetTestHostManager deps.json/runtimeconfig.dev.json parsing#16070
Conversation
…and runtimeconfig.dev.json parsing These tests verify that DotnetTestHostManager correctly reads real deps.json and runtimeconfig.dev.json files from disk to locate testhost.dll. They guard against regressions in DepsJsonParser (net framework) and the Jsonite-based runtimeconfig.dev.json parsing. Closes #15589 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds filesystem-backed tests for DotnetTestHostManager to cover real .deps.json, .runtimeconfig.json, and .runtimeconfig.dev.json handling paths that were previously only mocked.
Changes:
- Adds four tests that create temporary test assemblies/config files and use the real
FileHelper. - Verifies testhost discovery through deps/runtimeconfig.dev probing and fallback discovery next to the source DLL.
- Verifies launch arguments include
--depsfileand--runtimeconfigwhen corresponding files exist.
| File.WriteAllText(Path.Combine(_tempDir, "TestProject.runtimeconfig.dev.json"), runtimeConfigDevJson); | ||
|
|
||
| var manager = CreateManager(new FileHelper()); | ||
| manager.Initialize(_mockMessageLogger.Object, "<RunSettings><RunConfiguration><TargetFrameworkVersion>.NETCoreApp,Version=v8.0</TargetFrameworkVersion></RunConfiguration></RunSettings>"); |
nohwnd
left a comment
There was a problem hiding this comment.
Review: filesystem integration tests for DotnetTestHostManager
Activated dimensions (test/TestHostProvider path): Testhost Assembly Loading & Resolution, Process Architecture & Host Resolution, Cross-TFM & Framework Resolution, Acceptance Test Coverage Design.
What looks good
- Real
FileHelperused (no filesystem mock) — correctly exercisesDepsJsonParser/DependencyContextJsonReadercode paths. TearDowncleans up viaDirectory.Delete(recursive: true)— no leaked temp dirs.Guid.NewGuid()temp dir per run — tests are isolated and parallelism-safe.Assert.Contains(needle, haystack)calls are all correctly ordered (needle first).- JSON escaping of
packagesDiron Windows (Replace("\\", "\\\\")) is correct.
One issue
_mockDotnetHostHelper (line 43) — declared but never consumed. CreateManager instantiates a real DotnetHostHelper and this mock is never passed in. See inline comment.
Coverage note (non-blocking)
All four tests unconditionally mock PlatformOperatingSystem.Unix, so the Windows-specific testhost resolution path (.exe selection, Windows registry lookup) is not exercised. This is within the stated scope of the PR (guarding DepsJsonParser / runtimeconfig parsing), but a follow-up test covering the Windows platform branch would give fuller coverage.
🧠 Reviewed by Expert Code Reviewer
🧠 Reviewed by Expert Code Reviewer 🧠
| private readonly Mock<IRunSettingsHelper> _mockRunsettingsHelper = new(); | ||
| private readonly Mock<IWindowsRegistryHelper> _mockWindowsRegistry = new(); | ||
| private readonly Mock<IEnvironmentVariableHelper> _mockEnvironmentVariable = new(); | ||
| private readonly Mock<IDotnetHostHelper> _mockDotnetHostHelper = new(); |
There was a problem hiding this comment.
Dead field — _mockDotnetHostHelper is declared here but never referenced. CreateManager constructs a real DotnetHostHelper directly and this mock is never passed in. Either remove the field or wire it in if it was intended to allow mocking the dotnet host helper in future tests.
// Remove this line — it is unused:
private readonly Mock<IDotnetHostHelper> _mockDotnetHostHelper = new();There was a problem hiding this comment.
Done — removed the unused _mockDotnetHostHelper field.
🔧 Iterated by PR Iteration Agent 🔧
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Commit pushed:
|
🤖 Expert vstest review (automated)Test-only PR that adds 4 integration tests in 🛑 BlockersNone.
|
…arDown, remove no-op Replace
- Test 1: assert on testhostFullPath instead of substring 'microsoft.testplatform.testhost'
- Test 4: rename to FindsTestHostDllNextToSourceWhenNoDepsJson (no deps.json in that test)
- TearDown: wrap Directory.Delete in try/catch to avoid flakes on Windows
- Remove no-op .Replace("/", "/") from runtimeconfig.dev.json template
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Commit pushed:
|
|
Thanks for the review! I've addressed all the actionable suggestions:
|
| Assert.IsNotNull(startInfo.Arguments); | ||
| Assert.Contains(testhostFullPath, startInfo.Arguments); | ||
| } |
| /// These tests ensure that deps.json and runtimeconfig.dev.json parsing correctly locates testhost.dll | ||
| /// through the actual parsing code paths (DepsJsonParser on .NET Framework, DependencyContextJsonReader | ||
| /// on .NET Core, and Jsonite-based runtimeconfig.dev.json parsing). |
| [TestMethod] | ||
| public void GetTestHostProcessStartInfo_FindsTestHostDllNextToSourceWhenNoDepsJson() | ||
| { | ||
| // Arrange — no runtimeconfig.dev.json, testhost.dll is placed next to the source dll. |
| Assert.IsNotNull(startInfo.Arguments); | ||
| Assert.Contains(testhostFullPath, startInfo.Arguments); | ||
| } |
| /// These tests ensure that deps.json and runtimeconfig.dev.json parsing correctly locates testhost.dll | ||
| /// through the actual parsing code paths (DepsJsonParser on .NET Framework, DependencyContextJsonReader | ||
| /// on .NET Core, and Jsonite-based runtimeconfig.dev.json parsing). |
| [TestMethod] | ||
| public void GetTestHostProcessStartInfo_FindsTestHostDllNextToSourceWhenNoDepsJson() | ||
| { | ||
| // Arrange — no runtimeconfig.dev.json, testhost.dll is placed next to the source dll. |
nohwnd
left a comment
There was a problem hiding this comment.
Re-review after iteration
The previous finding (_mockDotnetHostHelper dead field) has been resolved — the field is no longer present in the current diff.
The code is clean:
Assert.Contains(needle, haystack)ordering is correct in all four assertions- Real
FileHelperis used — the parsing code paths are genuinely exercised - JSON escaping in the inline strings is correct (
/for deps.json library paths,\\\\for the probing path in runtimeconfig.dev.json) TearDowncleans up temp dirs with best-effort catch — no leaks
No further issues found.
🧠 Reviewed by Expert Code Reviewer 🧠
🧠 Reviewed by Expert Code Reviewer 🧠
🤖 This is an automated fix for issue #15589.
Root Cause
During the STJ migration,
DependencyContextJsonReaderwas replaced with a customDepsJsonParser(on .NET Framework) andJsonDocument.Parsewas replaced with Jsonite-based parsing forruntimeconfig.dev.json. When these replacements were made, no integration tests failed, proving the actual file-reading code paths were not exercised by any test — only mocked.What the fix does
Adds
DotnetTestHostManagerFilesystemIntegrationTests.cswith 4 tests that use realFileHelper(no mocking of the file system) and actual files on disk:FindsTestHostDllViaRealDepsJsonAndRuntimeConfigDevJson— Creates a realdeps.jsonpointing totesthost.dllin a nuget-like layout and a realruntimeconfig.dev.jsonwithadditionalProbingPaths. VerifiesGetTestHostProcessStartInfocorrectly parses both files and resolves the testhost path. This test would fail ifDepsJsonParseror the Jsonite runtimeconfig.dev.json parser is broken.PassesDepsFileArgWhenDepsJsonExists— Verifies--depsfileis included in testhost launch args when a real.deps.jsonexists on disk.PassesRuntimeConfigArgWhenRuntimeConfigExists— Verifies--runtimeconfigis included when a real.runtimeconfig.jsonexists on disk.FindsTestHostDllNextToSourceWhenNoRuntimeConfigDev— Verifies the fallback path (testhost.dll next to source dll) works when noruntimeconfig.dev.jsonis present.Tests
All 4 new tests pass on both
net11.0andnet481target frameworks.