如何在 Akka.NET 中使用 TestKit [英] How to use TestKit in Akka.NET

查看:45
本文介绍了如何在 Akka.NET 中使用 TestKit的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试测试我的 Akka.NET 演员,但在使用 TestKit 并理解其工作原理时遇到了一些问题.

I'm trying to test my Akka.NET actors, but are having some trouble with the TestKit and understanding how it works.

由于 Akka.NET 中还没有用于单元测试的官方文档,我已经探索了 Akka.NET 存储库的示例代码,但那里使用的示例对我不起作用.

Since there is no official documentation for unit testing in Akka.NET yet, I've explored the Akka.NET repo for example code, but the examples used there doesn't work for me.

我参考的测试是ReceiveActorTests.cs

The tests I've used for reference is ReceiveActorTests.cs and ReceiveActorTests_Become.cs, since those are close to the scenario I'm trying to test in my app.

这是一些虚拟代码:

给定这个演员

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);
        }
    }
}

我想测试它是否正确接收了 Greeting 和 Farewell 消息,并正确进入了 become-states.查看 BecomeActorTests,

I want to test that it Receives the Greeting and Farewell messages correctly, and enters the Become-states correctly. Looking at the ReceiveActorTests_Become.cs tests, an actor is created by

var system = ActorSystem.Create("test");
var actor = system.ActorOf<BecomeActor>("become");

并且一条消息由

actor.Tell(message, TestActor);
ExpectMsg(message);

但是,当我尝试这种方法来实例化一个 actor 以及许多其他基于 TestKit 方法(见下文)时,我不断收到同样失败的测试错误:

However, when I try this approach to instantiating an actor, and many others based on TestKit methods (see below), I keep getting the samme failed test error:

Xunit.Sdk.TrueExceptionFailed: Timeout 00:00:03 while waiting for a message of type ConsoleApplication1.Greeting 
Expected: True
Actual:   False

这是我的测试:

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);
    }
}

我还尝试将 ExpectMsg 线移到 actor.Tell 线上方(因为在您对某事采取行动之前先期盼某事并在之后验证期望值更有意义),但这也会导致超时错误.

I've also tried moving the ExpectMsg line above the actor.Tell line (since it made more sense to Expect something before you act on it and rather verify the expectation after), but this also results in the Timeout error.

我尝试过 NUnit 和 XUnit 测试套件.

I've tried with both NUnit and XUnit TestKits.

我可能忽略了一些非常基本的东西.

There's probably something really basic I've overlooked.

推荐答案

TestKit 用于更多行为测试,以验证您的 Actor 在整个 Actor 系统的上下文中是否按预期工作.这更像是黑盒测试——你不会直接接触到演员的内部.相反,最好专注于诸如给定信号 A 和参与者行为 B 之类的行为,它应该向另一个参与者 D 发送消息 C.

TestKit is used for more behavioral testing to verify if your actors work as expected in context of the whole actor system. This is more like black box testing - you don't reach the insides of an actor directly. Instead it's better to focus on behavior such as given signal A and actor behavior B it should emit message C to another actor D.

在您的 Greeter 演员的示例问题中,它是静音的 - 虽然它可以接收一些输入,但它不会产生任何结果.从整个系统的角度来看,它可能已经死了,没人会在意.

In your example problem with the Greeter actor is that it's mute - while it can receive some inputs, it doesn't do anything in result. From the perspective of the whole system it could be dead and nobody would care.

使用其他示例 - 给定以下演员:

Using other example - given following 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));
        });
    }
}

让我们创建一个示例测试规范:

Let's create an example test spec:

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");
    }
}

如你所见,这里我不检查actor的内部状态.相反,我正在观察它对我发送给它的信号的反应,并验证它是否是预期的结果.

As you can see, here I don't check the internal state of the actor. Instead I'm observing how it reacts on signals I send to it and verify if it's an expected result.

这篇关于如何在 Akka.NET 中使用 TestKit的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆