Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions TUnit.Core/Executors/GenericAbstractExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ public ValueTask ExecuteAfterTestHook(MethodMetadata hookMethodInfo, TestContext
return ExecuteAsync(action);
}

public ValueTask ExecuteDisposal(TestContext context, Func<ValueTask> action)
{
return ExecuteAsync(action);
}

public ValueTask ExecuteTest(TestContext context, Func<ValueTask> action)
{
return ExecuteAsync(action);
Expand Down
7 changes: 7 additions & 0 deletions TUnit.Core/Interfaces/IHookExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,11 @@ public interface IHookExecutor
ValueTask ExecuteAfterAssemblyHook(MethodMetadata hookMethodInfo, AssemblyHookContext context, Func<ValueTask> action);
ValueTask ExecuteAfterClassHook(MethodMetadata hookMethodInfo, ClassHookContext context, Func<ValueTask> action);
ValueTask ExecuteAfterTestHook(MethodMetadata hookMethodInfo, TestContext context, Func<ValueTask> action);

#if NETSTANDARD2_0
ValueTask ExecuteDisposal(TestContext context, Func<ValueTask> action);
#else
ValueTask ExecuteDisposal(TestContext context, Func<ValueTask> action)
=> action();
#endif
}
3 changes: 3 additions & 0 deletions TUnit.Engine/Discovery/ReflectionHookDiscoveryService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1029,4 +1029,7 @@ public ValueTask ExecuteBeforeTestSessionHook(MethodMetadata testMethod, TestSes

public ValueTask ExecuteAfterTestSessionHook(MethodMetadata testMethod, TestSessionContext context, Func<ValueTask> action)
=> action();

public ValueTask ExecuteDisposal(TestContext context, Func<ValueTask> action)
=> action();
}
4 changes: 3 additions & 1 deletion TUnit.Engine/Services/TestExecution/TestCoordinator.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Linq;
using TUnit.Core;
using TUnit.Core.Exceptions;
using TUnit.Core.Interfaces;
using TUnit.Core.Logging;
using TUnit.Core.Tracking;
using TUnit.Engine.Helpers;
Expand Down Expand Up @@ -152,7 +153,8 @@ await TimeoutHelper.ExecuteWithTimeoutAsync(

try
{
await TestExecutor.DisposeTestInstance(test).ConfigureAwait(false);
var hookExecutor = test.Context.CustomHookExecutor;
await TestExecutor.DisposeTestInstance(test, hookExecutor).ConfigureAwait(false);
}
catch (Exception disposeEx)
{
Expand Down
16 changes: 14 additions & 2 deletions TUnit.Engine/TestExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,12 +247,12 @@ public IContextProvider GetContextProvider()
return _contextProvider;
}

internal static async Task DisposeTestInstance(AbstractExecutableTest test)
internal static async Task DisposeTestInstance(AbstractExecutableTest test, IHookExecutor? hookExecutor = null)
{
// Dispose the test instance if it's disposable
if (test.Context.Metadata.TestDetails.ClassInstance is not SkippedTestInstance)
{
try
async ValueTask DisposeAsync()
{
var instance = test.Context.Metadata.TestDetails.ClassInstance;

Expand All @@ -266,6 +266,18 @@ internal static async Task DisposeTestInstance(AbstractExecutableTest test)
break;
}
}

try
{
if (hookExecutor != null)
{
await hookExecutor.ExecuteDisposal(test.Context, DisposeAsync).ConfigureAwait(false);
}
else
{
await DisposeAsync().ConfigureAwait(false);
}
}
catch
{
// Swallow disposal errors - they shouldn't fail the test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,7 @@ namespace
public . ExecuteBeforeTestDiscoveryHook(.MethodMetadata hookMethodInfo, .BeforeTestDiscoveryContext context, <.> action) { }
public . ExecuteBeforeTestHook(.MethodMetadata hookMethodInfo, .TestContext context, <.> action) { }
public . ExecuteBeforeTestSessionHook(.MethodMetadata hookMethodInfo, .TestSessionContext context, <.> action) { }
public . ExecuteDisposal(.TestContext context, <.> action) { }
public . ExecuteTest(.TestContext context, <.> action) { }
}
public sealed class GenericMethodInfo
Expand Down Expand Up @@ -2269,6 +2270,7 @@ namespace .Interfaces
. ExecuteBeforeTestDiscoveryHook(.MethodMetadata hookMethodInfo, .BeforeTestDiscoveryContext context, <.> action);
. ExecuteBeforeTestHook(.MethodMetadata hookMethodInfo, .TestContext context, <.> action);
. ExecuteBeforeTestSessionHook(.MethodMetadata hookMethodInfo, .TestSessionContext context, <.> action);
. ExecuteDisposal(.TestContext context, <.> action);
}
public interface IHookRegisteredEventReceiver : .
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,7 @@ namespace
public . ExecuteBeforeTestDiscoveryHook(.MethodMetadata hookMethodInfo, .BeforeTestDiscoveryContext context, <.> action) { }
public . ExecuteBeforeTestHook(.MethodMetadata hookMethodInfo, .TestContext context, <.> action) { }
public . ExecuteBeforeTestSessionHook(.MethodMetadata hookMethodInfo, .TestSessionContext context, <.> action) { }
public . ExecuteDisposal(.TestContext context, <.> action) { }
public . ExecuteTest(.TestContext context, <.> action) { }
}
public sealed class GenericMethodInfo
Expand Down Expand Up @@ -2269,6 +2270,7 @@ namespace .Interfaces
. ExecuteBeforeTestDiscoveryHook(.MethodMetadata hookMethodInfo, .BeforeTestDiscoveryContext context, <.> action);
. ExecuteBeforeTestHook(.MethodMetadata hookMethodInfo, .TestContext context, <.> action);
. ExecuteBeforeTestSessionHook(.MethodMetadata hookMethodInfo, .TestSessionContext context, <.> action);
. ExecuteDisposal(.TestContext context, <.> action);
}
public interface IHookRegisteredEventReceiver : .
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,7 @@ namespace
public . ExecuteBeforeTestDiscoveryHook(.MethodMetadata hookMethodInfo, .BeforeTestDiscoveryContext context, <.> action) { }
public . ExecuteBeforeTestHook(.MethodMetadata hookMethodInfo, .TestContext context, <.> action) { }
public . ExecuteBeforeTestSessionHook(.MethodMetadata hookMethodInfo, .TestSessionContext context, <.> action) { }
public . ExecuteDisposal(.TestContext context, <.> action) { }
public . ExecuteTest(.TestContext context, <.> action) { }
}
public sealed class GenericMethodInfo
Expand Down Expand Up @@ -2269,6 +2270,7 @@ namespace .Interfaces
. ExecuteBeforeTestDiscoveryHook(.MethodMetadata hookMethodInfo, .BeforeTestDiscoveryContext context, <.> action);
. ExecuteBeforeTestHook(.MethodMetadata hookMethodInfo, .TestContext context, <.> action);
. ExecuteBeforeTestSessionHook(.MethodMetadata hookMethodInfo, .TestSessionContext context, <.> action);
. ExecuteDisposal(.TestContext context, <.> action);
}
public interface IHookRegisteredEventReceiver : .
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,7 @@ namespace
public . ExecuteBeforeTestDiscoveryHook(.MethodMetadata hookMethodInfo, .BeforeTestDiscoveryContext context, <.> action) { }
public . ExecuteBeforeTestHook(.MethodMetadata hookMethodInfo, .TestContext context, <.> action) { }
public . ExecuteBeforeTestSessionHook(.MethodMetadata hookMethodInfo, .TestSessionContext context, <.> action) { }
public . ExecuteDisposal(.TestContext context, <.> action) { }
public . ExecuteTest(.TestContext context, <.> action) { }
}
public sealed class GenericMethodInfo
Expand Down Expand Up @@ -2201,6 +2202,7 @@ namespace .Interfaces
. ExecuteBeforeTestDiscoveryHook(.MethodMetadata hookMethodInfo, .BeforeTestDiscoveryContext context, <.> action);
. ExecuteBeforeTestHook(.MethodMetadata hookMethodInfo, .TestContext context, <.> action);
. ExecuteBeforeTestSessionHook(.MethodMetadata hookMethodInfo, .TestSessionContext context, <.> action);
. ExecuteDisposal(.TestContext context, <.> action);
}
public interface IHookRegisteredEventReceiver : .
{
Expand Down
33 changes: 33 additions & 0 deletions TUnit.TestProject/SetHookExecutorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,36 @@ public async Task Test_StaticHooksExecuteInCustomExecutor()
await Assert.That(Thread.CurrentThread.Name).IsEqualTo("CrossPlatformTestExecutor");
}
}

/// <summary>
/// Tests demonstrating SetHookExecutor affects disposal execution - Issue #3918
/// </summary>
[EngineTest(ExpectedResult.Pass)]
[SetBothExecutors] // This attribute sets both executors
public class DisposalWithHookExecutorTests : IAsyncDisposable
{
private static bool _disposalExecutedInCustomExecutor;

[Test]
public async Task Test_ExecutesInCustomExecutor()
{
// Test should execute in custom executor
await Assert.That(Thread.CurrentThread.Name).IsEqualTo("CrossPlatformTestExecutor");
await Assert.That(CrossPlatformTestExecutor.IsRunningInTestExecutor.Value).IsTrue();
}

public ValueTask DisposeAsync()
{
// Verify disposal runs in the custom executor
_disposalExecutedInCustomExecutor =
Thread.CurrentThread.Name == "CrossPlatformTestExecutor" &&
CrossPlatformTestExecutor.IsRunningInTestExecutor.Value;
return default;
}

[After(Class)]
public static async Task VerifyDisposalRanInCustomExecutor(ClassHookContext context)
{
await Assert.That(_disposalExecutedInCustomExecutor).IsTrue();
}
}
Loading