Akka.Net 使用 TestKit 测试子演员 creation/supervision
Akka.Net test Child actor creation/supervision with TestKit
我有 Akka.Net 类似于以下的代码,我正在尝试为其编写测试:
public class DoesSomethingActor : UntypedActor
{
protected override void OnReceive(object message)
{
}
}
public class ForwardsMessagesActor : UntypedActor
{
protected override void OnReceive(object message)
{
var actor = Context.ActorOf(Context.DI().Props<DoesSomethingActor>(), "DoesSomethingWorker");
for (int i = 0; i < 5; i++)
{
actor.Tell(message + " " + i);
}
}
}
我已经完成了这个测试,但我显然遗漏了一些东西,因为我根本没有使用太多的 TestKit。是否仍然没有关于如何使用 TestKit 进行测试的官方文档?
//creating actor mocks with Moq seems to confuse Akka - it just doesn't work
//but creating mock classes manually like this,
//then configuring them in the DI container works
public class DoesSomethingActorSpy : DoesSomethingActor
{
public static List<object> ReceivedMessages = new List<object>();
protected override void OnReceive(object message)
{
ReceivedMessages.Add(message);
}
}
[TestMethod]
public void ForwardsMessagesActor_Creates5Messages()
{
//set up DI container to use DoesSomethingActorSpy as a child actor
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<ForwardsMessagesActor>();
builder.RegisterType<DoesSomethingActorSpy>().As<DoesSomethingActor>();
IContainer container = builder.Build();
var propsResolver = new AutoFacDependencyResolver(container, Sys);
var actor = ActorOfAsTestActorRef<ForwardsMessagesActor>(propsResolver.Create<ForwardsMessagesActor>());
actor.Tell("Test");
//this looks wrong, I probably should be using something from TestKit
Thread.Sleep(10);
CollectionAssert.AreEquivalent(
new[] { "Test 0", "Test 1", "Test 2", "Test 3", "Test 4" },
DoesSomethingActorSpy.ReceivedMessages);
}
我应该如何创建模拟演员? TestKit 上是否有任何方法可以调用以等待所有消息都已处理?
引自How to Test Akka.NET Actors: Unit Testing w/ Akka.TestKit
:
Testing the parent/child relationship is more complicated. This is one case where Akka.NET's commitment to providing simple abstractions makes testing harder.
The simplest way to test this relationship is with messaging. For example, you can create a parent actor whose child messages another actor once it starts. Or you may have the parent forward a message to the child, and then the child can reply to the original sender, e.g.:
public class ChildActor : ReceiveActor
{
public ChildActor()
{
ReceiveAny(o => Sender.Tell("hello!"));
}
}
public class ParentActor : ReceiveActor
{
public ParentActor()
{
var child = Context.ActorOf(Props.Create(() => new ChildActor()));
ReceiveAny(o => child.Forward(o));
}
}
[TestFixture]
public class ParentGreeterSpecs : TestKit
{
[Test]
public void Parent_should_create_child()
{
// verify child has been created by sending parent a message
// that is forwarded to child, and which child replies to sender with
var parentProps = Props.Create(() => new ParentActor());
var parent = ActorOfAsTestActorRef<ParentActor>(parentProps, TestActor);
parent.Tell("this should be forwarded to the child");
ExpectMsg("hello!");
}
}
A Word of Caution On Testing Parent/Child Relationships
Avoid over-coupling your code to your hierarchy!
Over-testing parent/child relationships can couple your tests to your hierarchy implementation. This increases the costs of refactoring your code later on by forcing many test rewrites. You need to strike a balance between verifying your intent and testing your implementation.
我有 Akka.Net 类似于以下的代码,我正在尝试为其编写测试:
public class DoesSomethingActor : UntypedActor
{
protected override void OnReceive(object message)
{
}
}
public class ForwardsMessagesActor : UntypedActor
{
protected override void OnReceive(object message)
{
var actor = Context.ActorOf(Context.DI().Props<DoesSomethingActor>(), "DoesSomethingWorker");
for (int i = 0; i < 5; i++)
{
actor.Tell(message + " " + i);
}
}
}
我已经完成了这个测试,但我显然遗漏了一些东西,因为我根本没有使用太多的 TestKit。是否仍然没有关于如何使用 TestKit 进行测试的官方文档?
//creating actor mocks with Moq seems to confuse Akka - it just doesn't work
//but creating mock classes manually like this,
//then configuring them in the DI container works
public class DoesSomethingActorSpy : DoesSomethingActor
{
public static List<object> ReceivedMessages = new List<object>();
protected override void OnReceive(object message)
{
ReceivedMessages.Add(message);
}
}
[TestMethod]
public void ForwardsMessagesActor_Creates5Messages()
{
//set up DI container to use DoesSomethingActorSpy as a child actor
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<ForwardsMessagesActor>();
builder.RegisterType<DoesSomethingActorSpy>().As<DoesSomethingActor>();
IContainer container = builder.Build();
var propsResolver = new AutoFacDependencyResolver(container, Sys);
var actor = ActorOfAsTestActorRef<ForwardsMessagesActor>(propsResolver.Create<ForwardsMessagesActor>());
actor.Tell("Test");
//this looks wrong, I probably should be using something from TestKit
Thread.Sleep(10);
CollectionAssert.AreEquivalent(
new[] { "Test 0", "Test 1", "Test 2", "Test 3", "Test 4" },
DoesSomethingActorSpy.ReceivedMessages);
}
我应该如何创建模拟演员? TestKit 上是否有任何方法可以调用以等待所有消息都已处理?
引自How to Test Akka.NET Actors: Unit Testing w/ Akka.TestKit
:
Testing the parent/child relationship is more complicated. This is one case where Akka.NET's commitment to providing simple abstractions makes testing harder.
The simplest way to test this relationship is with messaging. For example, you can create a parent actor whose child messages another actor once it starts. Or you may have the parent forward a message to the child, and then the child can reply to the original sender, e.g.:
public class ChildActor : ReceiveActor { public ChildActor() { ReceiveAny(o => Sender.Tell("hello!")); } } public class ParentActor : ReceiveActor { public ParentActor() { var child = Context.ActorOf(Props.Create(() => new ChildActor())); ReceiveAny(o => child.Forward(o)); } } [TestFixture] public class ParentGreeterSpecs : TestKit { [Test] public void Parent_should_create_child() { // verify child has been created by sending parent a message // that is forwarded to child, and which child replies to sender with var parentProps = Props.Create(() => new ParentActor()); var parent = ActorOfAsTestActorRef<ParentActor>(parentProps, TestActor); parent.Tell("this should be forwarded to the child"); ExpectMsg("hello!"); } }
A Word of Caution On Testing Parent/Child Relationships
Avoid over-coupling your code to your hierarchy!
Over-testing parent/child relationships can couple your tests to your hierarchy implementation. This increases the costs of refactoring your code later on by forcing many test rewrites. You need to strike a balance between verifying your intent and testing your implementation.