Skip to content

Commit

Permalink
Add Akka.Hosting.TestKit module (#102)
Browse files Browse the repository at this point in the history
* Add Akka.Hosting.TestKit

* Add xunit.runner.json file

* Fix ImplicitSender

* Fix spec .csproj file

* Base the TestKit off TestKitBase instead

* Fix TestKit, test should start only after TestKit is initialized

* Fix TestEventListenerTest

* Change `ConfigureAkka` from virtual to abstract

* Refactor Akka.Persistence.Hosting.Tests to use Akka.Hosting.TestKit

Co-authored-by: Aaron Stannard <aaron@petabridge.com>
  • Loading branch information
Arkatufus and Aaronontheweb authored Oct 4, 2022
1 parent 89b70c4 commit cf87206
Show file tree
Hide file tree
Showing 45 changed files with 3,219 additions and 39 deletions.
12 changes: 12 additions & 0 deletions Akka.Hosting.sln
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Hosting.Te
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Hosting.LoggingDemo", "src\Examples\Akka.Hosting.LoggingDemo\Akka.Hosting.LoggingDemo.csproj", "{4F79325B-9EE7-4501-800F-7A1F8DFBCC80}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Hosting.TestKit", "src\Akka.Hosting.TestKit\Akka.Hosting.TestKit.csproj", "{E28D4F3C-6C34-497B-BDC8-F2B3EA8BA309}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Hosting.TestKit.Tests", "src\Akka.Hosting.TestKit.Tests\Akka.Hosting.TestKit.Tests.csproj", "{3883AD08-B981-4943-8153-1E7FFD2C3127}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -105,6 +109,14 @@ Global
{4F79325B-9EE7-4501-800F-7A1F8DFBCC80}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4F79325B-9EE7-4501-800F-7A1F8DFBCC80}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4F79325B-9EE7-4501-800F-7A1F8DFBCC80}.Release|Any CPU.Build.0 = Release|Any CPU
{E28D4F3C-6C34-497B-BDC8-F2B3EA8BA309}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E28D4F3C-6C34-497B-BDC8-F2B3EA8BA309}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E28D4F3C-6C34-497B-BDC8-F2B3EA8BA309}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E28D4F3C-6C34-497B-BDC8-F2B3EA8BA309}.Release|Any CPU.Build.0 = Release|Any CPU
{3883AD08-B981-4943-8153-1E7FFD2C3127}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3883AD08-B981-4943-8153-1E7FFD2C3127}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3883AD08-B981-4943-8153-1E7FFD2C3127}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3883AD08-B981-4943-8153-1E7FFD2C3127}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
28 changes: 28 additions & 0 deletions src/Akka.Hosting.TestKit.Tests/Akka.Hosting.TestKit.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(TestsNetCoreFramework)</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Akka.Hosting.TestKit\Akka.Hosting.TestKit.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="1.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
<PackageReference Include="xunit" Version="$(XunitVersion)" />
<PackageReference Include="FluentAssertions" Version="6.7.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitRunneVisualstudio)">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<None Update="xunit.runner.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
64 changes: 64 additions & 0 deletions src/Akka.Hosting.TestKit.Tests/HostingSpecSpec.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// -----------------------------------------------------------------------
// <copyright file="HostingSpecSpec.cs" company="Akka.NET Project">
// Copyright (C) 2009-2022 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------

using System;
using System.Threading.Tasks;
using Akka.Actor;
using Akka.Event;
using Akka.TestKit.TestActors;
using Xunit;
using Xunit.Abstractions;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;

namespace Akka.Hosting.TestKit.Tests
{
public class HostingSpecSpec: TestKit
{
private enum Echo
{ }

public HostingSpecSpec(ITestOutputHelper output)
: base(nameof(HostingSpecSpec), output, logLevel: LogLevel.Debug)
{
}

protected override Task ConfigureAkka(AkkaConfigurationBuilder builder, IServiceProvider provider)
{
builder.WithActors((system, registry) =>
{
var echo = system.ActorOf(Props.Create(() => new SimpleEchoActor()));
registry.Register<Echo>(echo);
});
return Task.CompletedTask;
}

[Fact]
public void ActorTest()
{
var echo = ActorRegistry.Get<Echo>();
var probe = CreateTestProbe();

echo.Tell("TestMessage", probe);
var msg = probe.ExpectMsg("TestMessage");
Log.Info(msg);
}

private class SimpleEchoActor : ReceiveActor
{
public SimpleEchoActor()
{
var log = Context.GetLogger();

ReceiveAny(msg =>
{
log.Info($"Received {msg}");
Sender.Tell(msg);
});
}
}
}
}
75 changes: 75 additions & 0 deletions src/Akka.Hosting.TestKit.Tests/NoImplicitSenderSpec.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//-----------------------------------------------------------------------
// <copyright file="NoImplicitSenderSpec.cs" company="Akka.NET Project">
// Copyright (C) 2009-2021 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2021 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
//-----------------------------------------------------------------------

using System;
using System.Threading.Tasks;
using Akka.Actor;
using Akka.Actor.Dsl;
using Akka.TestKit;
using FluentAssertions;
using Xunit;

namespace Akka.Hosting.TestKit.Tests;

public class NoImplicitSenderSpec : TestKit, INoImplicitSender
{
protected override Task ConfigureAkka(AkkaConfigurationBuilder builder, IServiceProvider provider)
{
return Task.CompletedTask;
}

[Fact]
public void When_Not_ImplicitSender_then_testActor_is_not_sender()
{
var echoActor = Sys.ActorOf(c => c.ReceiveAny((m, ctx) => TestActor.Tell(ctx.Sender)));
echoActor.Tell("message");
var actorRef = ExpectMsg<IActorRef>();
actorRef.Should().Be(Sys.DeadLetters);
}

}

public class ImplicitSenderSpec : TestKit
{
protected override Task ConfigureAkka(AkkaConfigurationBuilder builder, IServiceProvider provider)
{
return Task.CompletedTask;
}

[Fact]
public void ImplicitSender_should_have_testActor_as_sender()
{
var echoActor = Sys.ActorOf(c => c.ReceiveAny((m, ctx) => TestActor.Tell(ctx.Sender)));
echoActor.Tell("message");
ExpectMsg<IActorRef>(actorRef => Equals(actorRef, TestActor));

//Test that it works after we know that context has been changed
echoActor.Tell("message");
ExpectMsg<IActorRef>(actorRef => Equals(actorRef, TestActor));

}


[Fact]
public void ImplicitSender_should_not_change_when_creating_Testprobes()
{
//Verifies that bug #459 has been fixed
var testProbe = CreateTestProbe();
TestActor.Tell("message");
ReceiveOne();
LastSender.Should().Be(TestActor);
}

[Fact]
public void ImplicitSender_should_not_change_when_creating_TestActors()
{
var testActor2 = CreateTestActor("test2");
TestActor.Tell("message");
ReceiveOne();
LastSender.Should().Be(TestActor);
}
}
35 changes: 35 additions & 0 deletions src/Akka.Hosting.TestKit.Tests/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//-----------------------------------------------------------------------
// <copyright file="AssemblyInfo.cs" company="Akka.NET Project">
// Copyright (C) 2009-2021 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2021 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
//-----------------------------------------------------------------------

using System.Reflection;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
using Xunit;

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("b21496c0-a536-4953-9253-d2d0d526e42d")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]

[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly, DisableTestParallelization = true)]
55 changes: 55 additions & 0 deletions src/Akka.Hosting.TestKit.Tests/TestActorRefTests/BossActor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//-----------------------------------------------------------------------
// <copyright file="BossActor.cs" company="Akka.NET Project">
// Copyright (C) 2009-2021 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2021 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
//-----------------------------------------------------------------------

using System;
using Akka.Actor;
using Akka.TestKit;

namespace Akka.Hosting.TestKit.Tests.TestActorRefTests;

public class BossActor : TActorBase
{
private TestActorRef<InternalActor> _child;

public BossActor()
{
_child = new TestActorRef<InternalActor>(Context.System, Props.Create<InternalActor>(), Self, "child");
}

protected override SupervisorStrategy SupervisorStrategy()
{
return new OneForOneStrategy(maxNrOfRetries: 5, withinTimeRange: TimeSpan.FromSeconds(1), localOnlyDecider: ex => ex is ActorKilledException ? Directive.Restart : Directive.Escalate);
}

protected override bool ReceiveMessage(object message)
{
if(message is string && ((string)message) == "sendKill")
{
_child.Tell(Kill.Instance);
return true;
}
return false;
}

private class InternalActor : TActorBase
{
protected override void PreRestart(Exception reason, object message)
{
TestActorRefSpec.Counter--;
}

protected override void PostRestart(Exception reason)
{
TestActorRefSpec.Counter--;
}

protected override bool ReceiveMessage(object message)
{
return true;
}
}
}
56 changes: 56 additions & 0 deletions src/Akka.Hosting.TestKit.Tests/TestActorRefTests/FsmActor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//-----------------------------------------------------------------------
// <copyright file="FsmActor.cs" company="Akka.NET Project">
// Copyright (C) 2009-2021 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2021 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
//-----------------------------------------------------------------------

using Akka.Actor;

namespace Akka.Hosting.TestKit.Tests.TestActorRefTests;

public enum TestFsmState
{
First,
Last
}

public class FsmActor : FSM<TestFsmState, string>
{
private readonly IActorRef _replyActor;

public FsmActor(IActorRef replyActor)
{
_replyActor = replyActor;

When(TestFsmState.First, e =>
{
if (e.FsmEvent.Equals("check"))
{
_replyActor.Tell("first");
}
else if (e.FsmEvent.Equals("next"))
{
return GoTo(TestFsmState.Last);
}

return Stay();
});

When(TestFsmState.Last, e =>
{
if (e.FsmEvent.Equals("check"))
{
_replyActor.Tell("last");
}
else if (e.FsmEvent.Equals("next"))
{
return GoTo(TestFsmState.First);
}

return Stay();
});

StartWith(TestFsmState.First, "foo");
}
}
28 changes: 28 additions & 0 deletions src/Akka.Hosting.TestKit.Tests/TestActorRefTests/Logger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//-----------------------------------------------------------------------
// <copyright file="Logger.cs" company="Akka.NET Project">
// Copyright (C) 2009-2021 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2021 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
//-----------------------------------------------------------------------

using Akka.Actor;
using Akka.Event;

namespace Akka.Hosting.TestKit.Tests.TestActorRefTests;

public class Logger : ActorBase
{
private int _count;
private string _msg;
protected override bool Receive(object message)
{
var warning = message as Warning;
if(warning != null && warning.Message is string)
{
_count++;
_msg = (string)warning.Message;
return true;
}
return false;
}
}
Loading

0 comments on commit cf87206

Please sign in to comment.