Repository navigation
Description
Summary
Generic test discovery evaluates constructor-row factories to infer class types, then reuses the evaluated value for the first test and invokes the original factory for later tests. Generated and reflection discovery implement this lifecycle separately, so changes can make the modes create or reuse different objects. Consolidate the lifecycle without changing test behavior.
Reproduction
On origin/main at e8764cd10e, inspect GenericClassRowPartitionDataSource.FirstFetchReturnsEvaluatedRow in src/TUnit.Core/Attributes/TestData/GenericClassRowPartition.cs and FirstFetchRows in src/TUnit.Core/Attributes/TestData/StaticDataSourceAttribute.cs. Reflection discovery creates and shares first-fetch boxes in ReflectionTestDataCollector.GroupClassRowsByTypeArgumentsAsync in src/TUnit.Engine/Discovery/ReflectionTestDataCollector.cs.
Open PR #7422, at 615d7b4ceb882060529596f48a1706299e564a51, adds another first-fetch closure in MethodDataSourceAttribute.GetDataRowsAsync and parallel RowFactories arrays alongside FirstFetchRows. These additions are not yet on main; account for them if that PR lands before implementation. The existing duplication on main can already be refactored.
A generic class source returning IEnumerable<Func<Resource>> and a test with two method argument rows requires fresh resources for both tests while reusing the object already evaluated for inference once.
Proposal
Use a shared per-row state object containing the evaluated value and its original factory across both discovery modes. Replace parallel reflection arrays where practical.
Acceptance criteria
- Generated and reflection discovery use the same first-fetch state implementation, including any additional first-fetch paths from fix(generator): infer generic class types from class MethodDataSource rows #7422 that have landed by implementation time.
- Consume the evaluated value exactly once across sources sharing that row; subsequent fetches call the original factory for fresh values.
- Preserve wrapped
TestDataRowsettings, null-row behavior, and disposal ownership. - Validate existing fresh-factory and null-row fixtures in both discovery modes and Native AOT. Run affected generator snapshot tests if output changes, and public API tests if the public surface changes.
Found in PR #7422, concern 2. This remains a nonblocking refactor follow-up.
Activity
Share evaluated constructor-row state across discovery modes (#7443)
Share evaluated constructor-row state across discovery modes (#7443) (#…