diff --git a/TUnit.Engine/Services/PropertyInjector.cs b/TUnit.Engine/Services/PropertyInjector.cs index 92fd913b25..7dd08cfe5d 100644 --- a/TUnit.Engine/Services/PropertyInjector.cs +++ b/TUnit.Engine/Services/PropertyInjector.cs @@ -37,7 +37,7 @@ public PropertyInjector(Lazy initializationCallback, st /// Resolves and caches property values for a test class type WITHOUT setting them on an instance. /// Used during registration to create shared objects early and enable proper reference counting. /// - public async Task ResolveAndCachePropertiesAsync( + public Task ResolveAndCachePropertiesAsync( Type testClassType, ConcurrentDictionary objectBag, MethodMetadata? methodMetadata, @@ -47,16 +47,27 @@ public async Task ResolveAndCachePropertiesAsync( // Skip property resolution if this test is reusing the discovery instance (already initialized) if (testContext.IsDiscoveryInstanceReused) { - return; + return Task.CompletedTask; } var plan = PropertyInjectionCache.GetOrCreatePlan(testClassType); if (!plan.HasProperties) { - return; + return Task.CompletedTask; + } + + if (plan.SourceGeneratedProperties.Length > 0 || plan.ReflectionProperties.Length > 0) + { + return ResolveAndCachePropertiesCoreAsync(objectBag, methodMetadata, events, testContext, plan); } + return Task.CompletedTask; + } + + private async Task ResolveAndCachePropertiesCoreAsync(ConcurrentDictionary objectBag, MethodMetadata? methodMetadata, + TestContextEvents events, TestContext testContext, PropertyInjectionPlan plan) + { // Resolve properties based on what's available in the plan if (plan.SourceGeneratedProperties.Length > 0) { @@ -333,7 +344,7 @@ private async Task InjectReflectionPropertyAsync( propertySetter(instance, resolvedValue); } - private async Task RecurseIntoNestedPropertiesAsync( + private Task RecurseIntoNestedPropertiesAsync( object instance, PropertyInjectionPlan plan, ConcurrentDictionary objectBag, @@ -343,9 +354,21 @@ private async Task RecurseIntoNestedPropertiesAsync( { if (!plan.HasProperties) { - return; + return Task.CompletedTask; + } + + if (plan.SourceGeneratedProperties.Length > 0 || plan.ReflectionProperties.Length > 0) + { + return RecurseIntoNestedPropertiesCoreAsync(instance, plan, objectBag, methodMetadata, events, visitedObjects); } + return Task.CompletedTask; + } + + private async Task RecurseIntoNestedPropertiesCoreAsync(object instance, PropertyInjectionPlan plan, + ConcurrentDictionary objectBag, MethodMetadata? methodMetadata, TestContextEvents events, + ConcurrentDictionary visitedObjects) + { if (plan.SourceGeneratedProperties.Length > 0) { foreach (var metadata in plan.SourceGeneratedProperties)