簡體   English   中英

如何在Akka.NET中使用TestKit

[英]How to use TestKit in Akka.NET

我正在嘗試測試我的Akka.NET演員,但是在使用TestKit時遇到了一些問題,並了解它是如何工作的。

由於Akka.NET中沒有關於單元測試的官方文檔,我已經探索了Akka.NET repo的示例代碼,但是那里使用的示例對我不起作用。

我用於參考的測試是ReceiveActorTests.csReceiveActorTests_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);
        }
    }
}

我想測試它是否正確接收問候語和告別消息,並正確進入“成就狀態”。 查看ReceiveActorTests_Become.cs測試,創建一個actor

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

並且發送和斷言消息

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

但是,當我嘗試使用這種方法來實例化一個actor,以及許多其他基於TestKit方法的方法(見下文)時,我一直得到samme失敗的測試錯誤:

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線上方(因為在你采取行動之前對Expect做了更有意義的事情,而不是在之后驗證期望),但這也會導致Timeout錯誤。

我試過NUnit和XUnit TestKits。

我可能忽略了一些非常基本的東西。

TestKit用於更多行為測試,以驗證您的演員是否在整個演員系統的上下文中按預期工作。 這更像是黑盒測試 - 你沒有直接到達演員的內部。 相反,最好關注諸如給定信號A和演員行為B之類的行為,它應該將消息C發送給另一個演員D.

在你的示例中, Greeter actor的問題是它是靜音 - 雖然它可以接收一些輸入,但它不會在結果中做任何事情。 從整個系統的角度來看,它可能已經死了,沒人會關心。

使用其他示例 - 給出以下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));
        });
    }
}

讓我們創建一個示例測試規范:

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的內部狀態。 相反,我正在觀察它對我發送給它的信號的反應,並驗證它是否是預期的結果。

您沒有也不應該創建自己的ActorSystem作為任何Akka.TestKit測試的一部分。 您可以在任何測試中使用內置的Sys屬性,並且您將可以訪問TestKit本身使用的相同ActorSystem

所以你應該做這樣的事情:

var actor = Sys.ActorOf<BecomeActor>("become");

之所以這很重要 :除非你使用的是Akka.Remote,否則將TestActor和您的BecomeActor放在同一個ActorSystem是必要的,以便它們相互發送消息。 否則, TestActor無法接收任何消息,您的ExpectMsg調用將超時。

編輯:整個測試演員系統現在在單元測試之間被拆除。

編輯2:請參閱我們寫入Akka.NET TestKit詳細指南,以獲得更長的解釋

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM