Seed the test's environment before its modules apply - #54
Merged
Merged
Conversation
Module registrations are conditioned as they are applied: LoadModules answers [IfEnvironment] from the IModuleEnvironment already in the collection, or a process default when there is none. Both test runners loaded modules before the service-setup pass, so an environment a setup attribute registered arrived after every condition had been decided against the default - a test had no way to put itself under the environment it declares. Hardened's second framework trial hit exactly this: [EnvironmentName] on a test method against an [IfEnvironment] module, and the gated registration never applied. IModuleEnvironmentProvider is the new hook: an attribute names the environment, both runners consult it before loading any module, and the narrowest scope that answers decides. It lives in Runtime.Interfaces beside IDependencyModuleProvider and takes a MethodInfo rather than a test-method context, because it returns a Runtime type and Testing deliberately does not reference Runtime. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ipjohnson
added a commit
that referenced
this pull request
Sep 1, 2026
Version and changelog for #54. A minor version rather than a patch, because IModuleEnvironmentProvider is new public API on the Runtime package. FileVersion catches up two releases: the 1.2.3 cut moved VersionPrefix and left it at 1.2.2.0, though its own comment says it carries the real version for anyone inspecting the binary. Co-authored-by: Ian Johnson <ian.phillip.johnson@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This was referenced Sep 1, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Module registrations are conditioned as they are applied:
LoadModulesanswers[IfEnvironment]from theIModuleEnvironmentalready in the collection, or a process default when there is none. Both test runners loaded modules before the service-setup pass. An environment a setup attribute registered therefore arrived after every condition had been decided against the default, and a test had no way to put itself under the environment it declares.Hardened's second framework trial hit exactly this (finding D-B-10):
[EnvironmentName]on a test method against an[IfEnvironment]-gated registration, driven through the real xunit v3 entry point, and the gated registration never applied. The Hardened-side repro fails against 1.2.2 and passes against this branch, verified end to end with these packages packed locally.The fix is a new hook rather than a reorder. Running the service-setup pass before the modules would invert the documented contract that a test registration beats an application one, so the ordering stays and the environment gets its own, earlier step:
IModuleEnvironmentProviderinRuntime.Interfaces, besideIDependencyModuleProvider: an attribute names the environment for a test method, or returns null to defer to a wider scope.MethodInforather than a test-method context because it returns a Runtime type, and Testing deliberately does not reference Runtime - the same boundary the duplicated module loading in each runner exists to respect.Tests: xUnit and NUnit integ tests drive the seeding through the real runners - a
[SingletonService]+[IfEnvironment]registration applies under the seeded environment and stays absent without it, an environment-reading module sees the seeded instance, and the method-level seed beats the class-level one. The Runtime API snapshot gains the interface. The full solution suite passes on both TFMs.🤖 Generated with Claude Code