Skip to content

Conversation

@thomhurst
Copy link
Owner

Fixes #3992

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes issue #3992 by preventing IAsyncInitializer.InitializeAsync() from being called during test discovery. The fix introduces a new method InjectPropertiesAsync that performs property injection without triggering async initialization, deferring IAsyncInitializer calls to test execution time.

Key Changes:

  • Added InjectPropertiesAsync method to ObjectLifecycleService for property injection without async initialization
  • Updated TestBuilder to use InjectPropertiesAsync instead of EnsureInitializedAsync during discovery phase
  • Added regression test to verify IAsyncInitializer is not called during discovery

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
TUnit.TestProject/Bugs/3992/IAsyncInitializerDiscoveryTests.cs Regression test verifying IAsyncInitializer is only called during execution, not discovery
TUnit.Engine/Services/ObjectLifecycleService.cs Added new InjectPropertiesAsync method that injects properties without calling IAsyncInitializer
TUnit.Engine/Building/TestBuilder.cs Updated three call sites to use InjectPropertiesAsync instead of EnsureInitializedAsync during discovery

Comment on lines +220 to +223
if (obj == null)
{
throw new ArgumentNullException(nameof(obj));
}
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant null check: the generic constraint where T : notnull already ensures obj cannot be null at compile time. This check is unnecessary and can be removed.

Suggested change
if (obj == null)
{
throw new ArgumentNullException(nameof(obj));
}

Copilot uses AI. Check for mistakes.
Comment on lines +29 to +40
[Test]
[ClassDataSource<DataSourceWithAsyncInit>]
public async Task DataSource_InitializeAsync_OnlyCalledDuringExecution(DataSourceWithAsyncInit dataSource)
{
// Verify that the data source was initialized
await Assert.That(dataSource.IsInitialized).IsTrue();

// Verify that InitializeAsync was called (at least once during execution)
await Assert.That(_initializationCount).IsGreaterThan(0);

Console.WriteLine($"Test execution confirmed: InitializeAsync was called {_initializationCount} time(s)");
}
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test coverage gap: This test only covers method parameter data sources ([ClassDataSource<T>]). Consider adding a test case for property-based data sources as well, since properties can also use data source attributes and implement IAsyncInitializer.

Example:

public class PropertyDataSourceWithAsyncInit : IAsyncInitializer
{
    public bool IsInitialized { get; private set; }
    public Task InitializeAsync() { IsInitialized = true; return Task.CompletedTask; }
}

[PropertyDataSource<PropertyDataSourceWithAsyncInit>]
public PropertyDataSourceWithAsyncInit PropertyData { get; set; }

[Test]
public async Task PropertyDataSource_InitializeAsync_OnlyCalledDuringExecution()
{
    await Assert.That(PropertyData.IsInitialized).IsTrue();
}

Copilot uses AI. Check for mistakes.
@thomhurst thomhurst merged commit 60b47d0 into main Dec 6, 2025
16 of 19 checks passed
@thomhurst thomhurst deleted the bug/3992 branch December 6, 2025 11:24
@claude claude bot mentioned this pull request Dec 6, 2025
1 task
This was referenced Dec 8, 2025
This was referenced Dec 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Test discovery calls async initializers?

1 participant