ard*_*dal 10 c# unit-testing akka.net
我正在尝试测试我的Akka.NET演员,但是在使用TestKit时遇到了一些问题,并了解它是如何工作的.
由于Akka.NET中没有关于单元测试的官方文档,我已经探索了Akka.NET repo的示例代码,但是那里使用的示例对我不起作用.
我用于参考的测试是ReceiveActorTests.cs和ReceiveActorTests_Become.cs,因为那些接近我试图在我的应用程序中测试的场景.
这是一些虚拟代码:
鉴于这个演员
public class Greeter : ReceiveActor
{
public Greeter()
{
NotGreeted();
}
private void NotGreeted()
{
Receive<Greeting>(msg => Handle(msg));
}
private void Greeted()
{
Receive<Farewell>(msg => Handle(msg));
}
private void Handle(Greeting msg)
{
if (msg.Message == "hello")
{
Become(Greeted);
}
}
private void Handle(Farewell msg)
{
if (msg.Message == "bye bye")
{
Become(NotGreeted);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想测试它是否正确接收问候语和告别消息,并正确进入"成就状态".查看ReceiveActorTests_Become.cs测试,创建一个actor
var system = ActorSystem.Create("test");
var actor = system.ActorOf<BecomeActor>("become");
Run Code Online (Sandbox Code Playgroud)
并且发送和断言消息
actor.Tell(message, TestActor);
ExpectMsg(message);
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试使用这种方法来实例化一个actor,以及许多其他基于TestKit方法的方法(见下文)时,我一直得到samme失败的测试错误:
Xunit.Sdk.TrueExceptionFailed: Timeout 00:00:03 while waiting for a message of type ConsoleApplication1.Greeting
Expected: True
Actual: False
Run Code Online (Sandbox Code Playgroud)
这是我的测试:
public class XUnit_GreeterTests : TestKit
{
[Fact]
public void BecomesGreeted()
{
//var system = ActorSystem.Create("test-system"); // Timeout error
//var actor = system.ActorOf<Greeter>("greeter"); // Timeout error
//var actor = ActorOfAsTestActorRef<Greeter>("greeter"); // Timeout error
//var actor = ActorOf(() => new Greeter(), "greeter"); // Timeout error
//var actor = Sys.ActorOf<Greeter>("greeter"); // Timeout error
//var actor = Sys.ActorOf(Props.Create<Greeter>(), "greeter"); // Timeout error
var actor = CreateTestActor("greeter"); // Works, but doesn't test my Greeter actor, but rather creates a generic TestActor (as I understand it)
var message = new Greeting("hello");
actor.Tell(message, TestActor);
ExpectMsg(message);
}
}
Run Code Online (Sandbox Code Playgroud)
我也尝试将ExpectMsg线移到actor.Tell线上方(因为在你采取行动之前对Expect做了更有意义的事情,而不是在之后验证期望),但这也会导致Timeout错误.
我试过NUnit和XUnit TestKits.
我可能忽略了一些非常基本的东西.
Bar*_*ski 16
TestKit用于更多行为测试,以验证您的演员是否在整个演员系统的上下文中按预期工作.这更像是黑盒测试 - 你没有直接到达演员的内部.相反,它是更好地集中于行为,如给定的信号A和演员行为乙它应该发射消息C到另一个演员d.
在你的示例中,Greeteractor的问题是它是静音 - 虽然它可以接收一些输入,但它不会在结果中做任何事情.从整个系统的角度来看,它可能已经死了,没人会关心.
使用其他示例 - 给出以下actor:
public class Greeter : ReceiveActor
{
public Greeter()
{
Receive<Greet>(greet =>
{
// when message arrives, we publish it on the event stream
// and send response back to sender
Context.System.EventStream.Publish(greet.Who + " sends greetings");
Sender.Tell(new GreetBack(Self.Path.Name));
});
}
}
Run Code Online (Sandbox Code Playgroud)
让我们创建一个示例测试规范:
public class GreeterSpec : TestKit
{
private IActorRef greeter;
public GreeterSpec() : base()
{
greeter = Sys.ActorOf<Greeter>("TestGreeter");
}
[Fact]
public void Greeter_should_GreetBack_when_Greeted()
{
// set test actor as message sender
greeter.Tell(new Greet("John Snow"), TestActor);
// ExpectMsg tracks messages received by TestActors
ExpectMsg<GreetBack>(msg => msg.Who == "TestGreeter");
}
[Fact]
public void Greeter_should_broadcast_incoming_greetings()
{
// create test probe and subscribe it to the event bus
var subscriber = CreateTestProbe();
Sys.EventStream.Subscribe(subscriber.Ref, typeof (string));
greeter.Tell(new Greet("John Snow"), TestActor);
// check if subscriber received a message
subscriber.ExpectMsg<string>("John Snow sends greetings");
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,这里我不检查actor的内部状态.相反,我正在观察它对我发送给它的信号的反应,并验证它是否是预期的结果.
您没有也不应该创建自己ActorSystem的Akka.TestKit测试的一部分.您可以使用内置Sys的任何您的测试的财产,你会得到相同的访问ActorSystem所使用的TestKit本身.
所以你应该做这样的事情:
var actor = Sys.ActorOf<BecomeActor>("become");
Run Code Online (Sandbox Code Playgroud)
这很重要的原因:除非你使用的是Akka.Remote,否则必须拥有TestActor和你BecomeActor的相同ActorSystem才能让他们互相发送消息.否则TestActor无法接收任何消息,您的ExpectMsg通话将超时.
编辑:整个测试演员系统现在在单元测试之间被拆除.
编辑2:请参阅我们写给Akka.NET TestKit的详细指南,以获得更长的解释.
| 归档时间: |
|
| 查看次数: |
3350 次 |
| 最近记录: |