diff --git a/Akka.sln b/Akka.sln
index 4838b6b2d75..46bd08a19e4 100644
--- a/Akka.sln
+++ b/Akka.sln
@@ -279,6 +279,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.TestKit.Xunit2.Tests",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.TestKit.Xunit.Tests", "src\contrib\testkits\Akka.TestKit.Xunit.Tests\Akka.TestKit.Xunit.Tests.csproj", "{F80F41E6-E5C7-4C92-B1CF-42539ECFBE68}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Tests.Shared.Internals.Xunit3", "src\core\Akka.Tests.Shared.Internals.Xunit3\Akka.Tests.Shared.Internals.Xunit3.csproj", "{24DD484D-0F15-4D13-B603-F2E4A901CDBC}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1318,6 +1320,18 @@ Global
{F80F41E6-E5C7-4C92-B1CF-42539ECFBE68}.Release|x64.Build.0 = Release|Any CPU
{F80F41E6-E5C7-4C92-B1CF-42539ECFBE68}.Release|x86.ActiveCfg = Release|Any CPU
{F80F41E6-E5C7-4C92-B1CF-42539ECFBE68}.Release|x86.Build.0 = Release|Any CPU
+ {24DD484D-0F15-4D13-B603-F2E4A901CDBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {24DD484D-0F15-4D13-B603-F2E4A901CDBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {24DD484D-0F15-4D13-B603-F2E4A901CDBC}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {24DD484D-0F15-4D13-B603-F2E4A901CDBC}.Debug|x64.Build.0 = Debug|Any CPU
+ {24DD484D-0F15-4D13-B603-F2E4A901CDBC}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {24DD484D-0F15-4D13-B603-F2E4A901CDBC}.Debug|x86.Build.0 = Debug|Any CPU
+ {24DD484D-0F15-4D13-B603-F2E4A901CDBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {24DD484D-0F15-4D13-B603-F2E4A901CDBC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {24DD484D-0F15-4D13-B603-F2E4A901CDBC}.Release|x64.ActiveCfg = Release|Any CPU
+ {24DD484D-0F15-4D13-B603-F2E4A901CDBC}.Release|x64.Build.0 = Release|Any CPU
+ {24DD484D-0F15-4D13-B603-F2E4A901CDBC}.Release|x86.ActiveCfg = Release|Any CPU
+ {24DD484D-0F15-4D13-B603-F2E4A901CDBC}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1441,6 +1455,7 @@ Global
{337A85B5-4A7C-4883-8634-46E7E52A765F} = {7735F35A-E7B7-44DE-B6FB-C770B53EB69C}
{95017C99-E960-44E5-83AD-BF21461DF06F} = {7625FD95-4B2C-4A5B-BDD5-94B1493FAC8E}
{F80F41E6-E5C7-4C92-B1CF-42539ECFBE68} = {7625FD95-4B2C-4A5B-BDD5-94B1493FAC8E}
+ {24DD484D-0F15-4D13-B603-F2E4A901CDBC} = {01167D3C-49C4-4CDE-9787-C176D139ACDD}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {03AD8E21-7507-4E68-A4E9-F4A7E7273164}
diff --git a/Directory.Build.props b/Directory.Build.props
index 838680f9280..0d8329302b7 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -37,6 +37,7 @@
5.10.3
true
2.16.6
+ 3.3.2
2.0.3
6.0.1
1.5.40
diff --git a/src/core/Akka.Tests.Shared.Internals.Xunit3/ActorDslExtensions.cs b/src/core/Akka.Tests.Shared.Internals.Xunit3/ActorDslExtensions.cs
new file mode 100644
index 00000000000..0f4d1b7d7b0
--- /dev/null
+++ b/src/core/Akka.Tests.Shared.Internals.Xunit3/ActorDslExtensions.cs
@@ -0,0 +1,21 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (C) 2009-2022 Lightbend Inc.
+// Copyright (C) 2013-2025 .NET Foundation
+//
+//-----------------------------------------------------------------------
+
+using System;
+using Akka.Actor;
+using Akka.Actor.Dsl;
+
+// ReSharper disable once CheckNamespace
+namespace Akka.TestKit;
+
+public static class ActorDslExtensions
+{
+ public static void Receive(this IActorDsl config, string message, Action handler)
+ {
+ config.Receive(m=>string.Equals(m,message,StringComparison.Ordinal), handler);
+ }
+}
\ No newline at end of file
diff --git a/src/core/Akka.Tests.Shared.Internals.Xunit3/Akka.Tests.Shared.Internals.Xunit3.csproj b/src/core/Akka.Tests.Shared.Internals.Xunit3/Akka.Tests.Shared.Internals.Xunit3.csproj
new file mode 100644
index 00000000000..8cd8d03b5b9
--- /dev/null
+++ b/src/core/Akka.Tests.Shared.Internals.Xunit3/Akka.Tests.Shared.Internals.Xunit3.csproj
@@ -0,0 +1,20 @@
+
+
+ $(NetStandardLibVersion)
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/core/Akka.Tests.Shared.Internals.Xunit3/AkkaSpec.cs b/src/core/Akka.Tests.Shared.Internals.Xunit3/AkkaSpec.cs
new file mode 100644
index 00000000000..99c7e7fa58d
--- /dev/null
+++ b/src/core/Akka.Tests.Shared.Internals.Xunit3/AkkaSpec.cs
@@ -0,0 +1,351 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (C) 2009-2022 Lightbend Inc.
+// Copyright (C) 2013-2025 .NET Foundation
+//
+//-----------------------------------------------------------------------
+
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Akka.Actor;
+using Akka.Actor.Setup;
+using Akka.Configuration;
+using Akka.TestKit.Internal.StringMatcher;
+using Akka.TestKit.TestEvent;
+using Akka.Util.Internal;
+using Xunit;
+using Xunit.Sdk;
+
+// ReSharper disable once CheckNamespace
+namespace Akka.TestKit;
+
+public abstract class AkkaSpec : Xunit.TestKit //AkkaSpec is not part of TestKit
+{
+ private static Regex _nameReplaceRegex = new("[^a-zA-Z0-9]", RegexOptions.Compiled);
+ private static readonly Config _akkaSpecConfig = ConfigurationFactory.ParseString(
+ """
+ akka {
+ loglevel = WARNING
+ stdout-loglevel = WARNING
+ serialize-messages = on
+ actor {
+ ask-timeout = 20s
+ }
+ }
+ # use random ports to avoid race conditions with binding contention
+ akka.remote.dot-netty.tcp.port = 0
+ """);
+
+ private static int _systemNumber = 0;
+
+ private static ActorSystemSetup FromActorSystemSetup(ActorSystemSetup setup)
+ {
+ var bootstrapOptions = setup.Get();
+ var bootstrap = bootstrapOptions.HasValue ? bootstrapOptions.Value : BootstrapSetup.Create();
+ bootstrap = bootstrap.WithConfigFallback(_akkaSpecConfig);
+ return setup.And(bootstrap);
+ }
+
+ public AkkaSpec(string config, ITestOutputHelper output = null)
+ : this(ConfigurationFactory.ParseString(config).WithFallback(_akkaSpecConfig), output)
+ {
+ }
+
+ public AkkaSpec(Config config = null, ITestOutputHelper output = null)
+ : base(config.SafeWithFallback(_akkaSpecConfig), GetCallerName(), output)
+ {
+ BeforeAll();
+ }
+
+ public AkkaSpec(ActorSystemSetup setup, ITestOutputHelper output = null)
+ : base(FromActorSystemSetup(setup), GetCallerName(), output)
+ {
+ BeforeAll();
+ }
+
+ public AkkaSpec(ITestOutputHelper output, Config config = null)
+ : base(config.SafeWithFallback(_akkaSpecConfig), GetCallerName(), output)
+ {
+ BeforeAll();
+ }
+
+ public AkkaSpec(ActorSystem system, ITestOutputHelper output = null)
+ : base(system, output)
+ {
+ BeforeAll();
+ }
+
+ private void BeforeAll()
+ {
+ GC.Collect();
+ AtStartup();
+ }
+
+ protected override void AfterAll()
+ {
+ BeforeTermination();
+ base.AfterAll();
+ AfterTermination();
+ }
+
+ protected virtual void AtStartup() { }
+
+ protected virtual void BeforeTermination()
+ {
+ }
+
+ protected virtual void AfterTermination()
+ {
+ }
+
+ private static string GetCallerName()
+ {
+ var systemNumber = Interlocked.Increment(ref _systemNumber);
+ var stackTrace = new StackTrace(0);
+ var name = stackTrace.GetFrames()?
+ .Select(f => f.GetMethod())
+ .Where(m => m.DeclaringType != null)
+ .SkipWhile(m => m.DeclaringType.Name == "AkkaSpec")
+ .Select(m => _nameReplaceRegex.Replace(m.DeclaringType.Name + "-" + systemNumber, "-"))
+ .FirstOrDefault() ?? "test";
+
+ return name;
+ }
+
+ public static Config AkkaSpecConfig { get { return _akkaSpecConfig; } }
+
+ protected T ExpectMsgOf(
+ TimeSpan? timeout,
+ string hint,
+ Func