Skip to content

Share evaluated constructor-row state between generated and reflection discovery #7443

Closed

Description

@thomhurst

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 TestDataRow settings, 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low: cleanup, minor enhancement, or rare edge caseenhancementNew feature or requestin-progressWork is in progress

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions