-
-
Notifications
You must be signed in to change notification settings - Fork 108
fix: initialize IAsyncInitializer on data sources before constructor injection #4435
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: initialize IAsyncInitializer on data sources before constructor injection #4435
Conversation
SummaryFixes initialization of IAsyncInitializer data sources before constructor injection by properly calling InitializeAsync during execution phase. Critical IssuesNone found ✅ AnalysisThis PR correctly addresses issue #4432 by fixing a phase mismatch bug: The Bug: In The Fix:
TUnit Rules Compliance: Test Coverage:
Verdict✅ APPROVE - No critical issues. This is a clean, focused bug fix that correctly addresses the initialization phase mismatch. |
1526525 to
626b510
Compare
SummaryFixes data sources implementing IAsyncInitializer not being initialized before being passed to test class constructors. Critical IssuesNone found ✅ Suggestions1. Missing null check in new method (minor)In if (obj is null)
{
return;
}However, in foreach (var data in classData)
{
await _objectLifecycleService.InitializeObjectForExecutionAsync(data);
}This is correct, but you might consider whether the loop should skip null entries to avoid unnecessary async method calls, similar to how it's done elsewhere in the codebase (e.g., 2. Documentation clarityThe new method
This distinction is important for understanding the fix. 3. Consistency checkThe fix correctly initializes class data before constructor injection at TestBuilder.cs:69-72. This matches the execution-time initialization pattern used elsewhere. The key insight is that class data objects need execution-time initialization (IAsyncInitializer) not just discovery-time initialization (IAsyncDiscoveryInitializer), because they're being used during test execution (passed to constructor). The old code at line 70 called Verdict✅ APPROVE - No critical issues The fix is sound and follows TUnit's dual-mode principle correctly. The new |
…injection When a data source implementing IAsyncInitializer is passed to the test class constructor, its InitializeAsync() method was not being called before the constructor ran. This caused the fixture to be uninitialized when accessed in the constructor. The fix adds InitializeObjectForExecutionAsync() to ObjectLifecycleService which initializes an object and its nested IAsyncInitializer objects. TestBuilder now calls this method for each class data item before creating the test instance. Fixes #4432 Co-Authored-By: Claude Opus 4.5 <[email protected]>
626b510 to
4de4733
Compare
SummaryFixes data sources implementing Critical IssuesNone found ✅ AnalysisChanges Review1. TestBuilder.cs (TUnit.Engine/Building/TestBuilder.cs:69-70)
2. ObjectLifecycleService.cs (TUnit.Engine/Services/ObjectLifecycleService.cs:154-167)
3. Test Coverage (TUnit.TestProject/Bugs/4432/ConstructorInjectionAsyncInitializerTests.cs)
TUnit Rules Compliance✅ Dual-Mode: Not applicable - changes are in reflection-only Engine code, not metadata collection Design QualityThe fix correctly addresses the issue by:
The comprehensive test coverage ensures this specific bug (fixtures not initialized before constructor) won't regress. Verdict✅ APPROVE - No critical issues Well-structured fix that properly handles the execution-time initialization of constructor-injected data sources implementing |
When processing attributes with array constructor arguments (like params Type[]), the source generator was accessing .Value directly which throws InvalidOperationException for arrays. Now properly checks for array kind and iterates over .Values instead. This ensures concrete generic types within array arguments are also discovered. Co-Authored-By: Claude Opus 4.5 <[email protected]>
SummaryFixes IAsyncInitializer data sources not being initialized before constructor injection by replacing discovery-phase initialization with execution-phase initialization. Critical IssuesNone found ✅ AnalysisThis PR correctly fixes issue #4432 where Root Cause:
The Fix:
TUnit Rules Compliance: Test Coverage:
All tests marked with Note on Existing ReviewsI see you've already posted three thorough self-reviews on this PR. While self-reviews can be helpful for documentation, typically PR reviews come from other team members. Your analysis is solid and comprehensive. Verdict✅ APPROVE - Clean, focused bug fix with excellent test coverage that properly addresses the initialization phase mismatch. |
- NonInitializerFixtureTests: regression test for fixtures without IAsyncInitializer - MethodLevelInjectionTests: test method-level data source injection - NonGenericMultiTypeTests: test non-generic ClassDataSource with params Type[] (tests source generator array handling fix) Co-Authored-By: Claude Opus 4.5 <[email protected]>
SummaryFixes data sources implementing IAsyncInitializer not being initialized before constructor injection. Critical IssuesNone found Suggestions1. Source Generator: Array handlingThe new array handling code looks good and addresses the bug for non-generic ClassDataSource syntax. However, consider adding a clarifying comment that both array and single-value paths are needed for different attribute syntaxes. 2. Method naming consistencyThe new InitializeObjectForExecutionAsync method is well-documented and follows the execution-phase pattern. Nice work maintaining the discovery/execution phase separation. 3. Dual-mode verificationChanges properly handle both source-gen and reflection modes:
4. Test coverageThe regression test suite is exceptionally thorough:
5. Performance consideration (minor)In TestBuilder.cs:69-72, consider using a ValueListBuilder pattern to avoid Task allocations in hot paths. Not critical for this PR. VerdictAPPROVE - No critical issues Excellent fix with thorough testing. The dual-mode implementation is correct, the phase separation is maintained, and the regression tests are comprehensive. |
Summary
IAsyncInitializernot being initialized before being passed to the test class constructorInitializeClassDataForExecutionAsync()to call execution-time initialization on class data before instance creationFixes #4432
Test plan
ConstructorInjectionAsyncInitializerTestsverifies fixture is initialized before constructor[EngineTest(ExpectedResult.Pass)]tests pass🤖 Generated with Claude Code