Skip to content
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<CoverletVersion>6.0.3</CoverletVersion>
<XunitRunneVisualstudio>3.1.5</XunitRunneVisualstudio>
<Xunit3RunneVisualstudio>3.1.5</Xunit3RunneVisualstudio>
<AkkaVersion>1.5.67</AkkaVersion>
<AkkaVersion>1.5.68</AkkaVersion>
<MicrosoftExtensionsVersion>[9.0.0,)</MicrosoftExtensionsVersion>
<SystemTextJsonVersion>[9.0.0,)</SystemTextJsonVersion>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ namespace Akka.Hosting.TestKit
public System.Threading.Tasks.Task WithSnapshotSave(System.Func<Akka.Persistence.TestKit.SnapshotStoreSaveBehavior, System.Threading.Tasks.Task> behaviorSelector, System.Action execution) { }
public System.Threading.Tasks.Task WithSnapshotSave(System.Func<Akka.Persistence.TestKit.SnapshotStoreSaveBehavior, System.Threading.Tasks.Task> behaviorSelector, System.Func<System.Threading.Tasks.Task> execution) { }
}
[Akka.TestKit.Xunit.Attributes.AkkaCleanAmbientContext]
public abstract class TestKit : Akka.TestKit.TestKitBase, System.IAsyncDisposable, Xunit.IAsyncLifetime
{
protected TestKit(string? actorSystemName = null, Xunit.ITestOutputHelper? output = null, System.TimeSpan? startupTimeout = default, Microsoft.Extensions.Logging.LogLevel logLevel = 2) { }
Expand Down
83 changes: 83 additions & 0 deletions src/Akka.Hosting.TestKit.Tests/ParallelAmbientContextSpec.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// -----------------------------------------------------------------------
// <copyright file="ParallelAmbientContextSpec.cs" company="Akka.NET Project">
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------

using System;
using System.Threading.Tasks;
using Akka.Actor;
using Akka.Actor.Internal;
using Akka.TestKit;
using Xunit;

namespace Akka.Hosting.TestKit.Tests;

public abstract class ParallelAmbientContextSpecBase : TestKit
{
protected override void ConfigureAkka(AkkaConfigurationBuilder builder, IServiceProvider provider)
{
}

[Fact]
public async Task Implicit_sender_should_resolve_to_own_TestActor()
{
TestActor.Tell("ping");
await ExpectMsgAsync<string>(
"ping",
TimeSpan.FromSeconds(5),
cancellationToken: TestContext.Current.CancellationToken);
Assert.Equal(TestActor, LastSender);

await Task.Yield();
TestActor.Tell("ping-after-yield");
await ExpectMsgAsync<string>(
"ping-after-yield",
TimeSpan.FromSeconds(5),
cancellationToken: TestContext.Current.CancellationToken);
Assert.Equal(TestActor, LastSender);
}
}

public class ParallelAmbientContextSpec01 : ParallelAmbientContextSpecBase { }
public class ParallelAmbientContextSpec02 : ParallelAmbientContextSpecBase { }
public class ParallelAmbientContextSpec03 : ParallelAmbientContextSpecBase { }
public class ParallelAmbientContextSpec04 : ParallelAmbientContextSpecBase { }
public class ParallelAmbientContextSpec05 : ParallelAmbientContextSpecBase { }
public class ParallelAmbientContextSpec06 : ParallelAmbientContextSpecBase { }
public class ParallelAmbientContextSpec07 : ParallelAmbientContextSpecBase { }
public class ParallelAmbientContextSpec08 : ParallelAmbientContextSpecBase { }
public class ParallelAmbientContextSpec09 : ParallelAmbientContextSpecBase { }
public class ParallelAmbientContextSpec10 : ParallelAmbientContextSpecBase { }
public class ParallelAmbientContextSpec11 : ParallelAmbientContextSpecBase { }
public class ParallelAmbientContextSpec12 : ParallelAmbientContextSpecBase { }
public class ParallelAmbientContextSpec13 : ParallelAmbientContextSpecBase { }
public class ParallelAmbientContextSpec14 : ParallelAmbientContextSpecBase { }
public class ParallelAmbientContextSpec15 : ParallelAmbientContextSpecBase { }
public class ParallelAmbientContextSpec16 : ParallelAmbientContextSpecBase { }

public abstract class ParallelNoImplicitSenderSpecBase : TestKit, INoImplicitSender
{
protected override void ConfigureAkka(AkkaConfigurationBuilder builder, IServiceProvider provider)
{
}

[Fact]
public async Task Current_should_be_null_both_pre_and_post_await()
{
Assert.Null(InternalCurrentActorCellKeeper.Current);
await Task.Yield();
Assert.Null(InternalCurrentActorCellKeeper.Current);
await Task.Yield();
Assert.Null(InternalCurrentActorCellKeeper.Current);
}
}

public class ParallelNoImplicitSenderSpec01 : ParallelNoImplicitSenderSpecBase { }
public class ParallelNoImplicitSenderSpec02 : ParallelNoImplicitSenderSpecBase { }
public class ParallelNoImplicitSenderSpec03 : ParallelNoImplicitSenderSpecBase { }
public class ParallelNoImplicitSenderSpec04 : ParallelNoImplicitSenderSpecBase { }
public class ParallelNoImplicitSenderSpec05 : ParallelNoImplicitSenderSpecBase { }
public class ParallelNoImplicitSenderSpec06 : ParallelNoImplicitSenderSpecBase { }
public class ParallelNoImplicitSenderSpec07 : ParallelNoImplicitSenderSpecBase { }
public class ParallelNoImplicitSenderSpec08 : ParallelNoImplicitSenderSpecBase { }
2 changes: 1 addition & 1 deletion src/Akka.Hosting.TestKit.Tests/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]

[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly, DisableTestParallelization = true)]
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerClass)]
4 changes: 2 additions & 2 deletions src/Akka.Hosting.TestKit.Tests/xunit.runner.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://xunit.github.io/schema/current/xunit.runner.schema.json",
"longRunningTestSeconds": 60,
"parallelizeAssembly": false,
"parallelizeTestCollections": false
"parallelizeAssembly": true,
"parallelizeTestCollections": true
}
13 changes: 1 addition & 12 deletions src/Akka.Hosting.TestKit/TestKit.Shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public IHost Host
/// </summary>
private void EnsureImplicitSender()
{
if (this is not INoImplicitSender && TestActor != null)
if (this is not INoImplicitSender && InternalCurrentActorCellKeeper.Current == null && TestActor != null)
InternalCurrentActorCellKeeper.Current = (ActorCell)((ActorRefWithCell)TestActor).Underlying;
}

Expand Down Expand Up @@ -192,12 +192,6 @@ private async Task InitializeAsyncCore()
// TestActor initialization and registration now happens in AddStartup
// before user actors are created, preventing race conditions

// ALWAYS set the implicit sender context on the current thread after initialization
// This ensures it's available on the thread where tests will run
// This is critical for tests using DI-created actors
if (this is not INoImplicitSender && TestActor != null)
InternalCurrentActorCellKeeper.Current = (ActorCell)((ActorRefWithCell)TestActor).Underlying;

await BeforeTestStart();
}

Expand All @@ -221,11 +215,6 @@ protected sealed override void InitializeTest(ActorSystem system, ActorSystemSet

protected virtual Task BeforeTestStart()
{
// Ensure the implicit sender is set on the current thread before each test
// This is critical because tests may run on different threads than initialization
if (this is not INoImplicitSender)
InternalCurrentActorCellKeeper.Current = (ActorCell)((ActorRefWithCell)TestActor).Underlying;

return Task.CompletedTask;
}

Expand Down
2 changes: 2 additions & 0 deletions src/Akka.Hosting.TestKit/TestKit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
using System;
using System.Threading.Tasks;
using Akka.Annotations;
using Akka.TestKit.Xunit.Attributes;
using Xunit;

namespace Akka.Hosting.TestKit
{
[AkkaCleanAmbientContext]
public abstract partial class TestKit : IAsyncLifetime, IAsyncDisposable
{
[InternalApi]
Expand Down
Loading