Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在Akka.NET中使用TestKit_C#_Unit Testing_Akka.net - Fatal编程技术网

C# 如何在Akka.NET中使用TestKit

C# 如何在Akka.NET中使用TestKit,c#,unit-testing,akka.net,C#,Unit Testing,Akka.net,我正在尝试测试我的Akka.NET演员,但是在测试工具包和理解它的工作原理方面遇到了一些问题 由于Akka.NET中还没有关于单元测试的官方文档,因此我已经研究了Akka.NET repo示例代码,但是那里使用的示例对我来说并不适用 我用于参考的测试是和,因为它们接近我在应用程序中尝试测试的场景 下面是一些伪代码: 考虑到这个演员 public class Greeter : ReceiveActor { public Greeter() { NotGreeted

我正在尝试测试我的Akka.NET演员,但是在测试工具包和理解它的工作原理方面遇到了一些问题

由于Akka.NET中还没有关于单元测试的官方文档,因此我已经研究了Akka.NET repo示例代码,但是那里使用的示例对我来说并不适用

我用于参考的测试是和,因为它们接近我在应用程序中尝试测试的场景

下面是一些伪代码:

考虑到这个演员

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);
        }
    }
}
然而,当我尝试这种方法来实例化一个参与者,以及许多其他基于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);
    }
}
公共类XUnit\u GreeterTests:TestKit
{
[事实]
公共空间变得明显
{
//var system=ActorSystem.Create(“测试系统”);//超时错误
//var actor=system.ActorOf(“greeter”);//超时错误
//var actor=actorofastestactoref(“问候者”);//超时错误
//var actor=ActorOf(()=>new Greeter(),“Greeter”);//超时错误
//var actor=Sys.ActorOf(“问候者”);//超时错误
//var actor=Sys.ActorOf(Props.Create(),“greeter”);//超时错误
var actor=CreateTestActor(“greeter”);//工作正常,但不测试我的greeter actor,而是创建一个通用测试器(据我所知)
var消息=新问候语(“你好”);
actor.Tell(消息、测试者);
ExpectMsg(消息);
}
}
我还尝试将ExpectMsg行移到actor.Tell行的上方(因为在执行操作之前预期某些内容更合理,而在执行操作之后验证预期),但这也会导致超时错误

我试过NUnit和XUnit测试套件


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

作为任何Akka.TestKit测试的一部分,您不应该也不应该创建自己的
ActorSystem
。您可以在任何测试中使用内置的
Sys
属性,并且可以访问
TestKit
本身使用的
ActorSystem

所以你应该这样做:

var actor = Sys.ActorOf<BecomeActor>("become");
var actor=Sys.ActorOf(“变成”);
这一点很重要的原因:除非您使用的是Akka.Remote,否则在同一个
Actor系统中有必要让
测试者
和您的
成为参与者
。否则,
TestActor
将无法接收任何消息,您的
ExpectMsg
调用将超时

编辑:整个测试参与者系统现在在单元测试之间被拆毁


编辑2:请参阅。

测试工具包用于更多的行为测试,以验证您的参与者是否在整个参与者系统的上下文中按预期工作。这更像是黑盒测试——你不能直接接触到演员的内心。相反,最好关注行为,例如给定的信号A和参与者行为B,它应该向另一个参与者D发出消息C

在您的示例中,
Greeter
actor的问题在于它是静音的——虽然它可以接收一些输入,但结果却不做任何事情。从整个系统的角度来看,它可能已经死了,没有人会在意

使用其他示例-给定以下参与者:

公共类迎宾员:ReceiveActor
{
公共迎宾员()
{
接收(问候=>
{
//当消息到达时,我们将其发布到事件流中
//并将响应发送回发件人
Context.System.EventStream.Publish(greet.Who+“发送问候”);
Tell(新GreetBack(Self.Path.Name));
});
}
}
让我们创建一个示例测试规范:

公共类GreeterSpec:TestKit { 私人迎宾员; 公共GreeterSpec():base() { greeter=Sys.ActorOf(“TestGreeter”); } [事实] 公共无效问候者应在问候时问候对方() { //将测试参与者设置为消息发送者 问候者。告诉(新问候语(“约翰·斯诺”),遗嘱执行者); //ExpectMsg跟踪测试者收到的消息 ExpectMsg(msg=>msg.Who==“TestGreeter”); } [事实] 公共空间问候者应广播问候语 { //创建测试探针并将其订阅到事件总线 var subscriber=CreateTestProbe(); Sys.EventStream.Subscribe(subscriber.Ref,typeof(string)); 问候者。告诉(新问候语(“约翰·斯诺”),遗嘱执行者); //检查订户是否收到消息 ExpectMsg(“John Snow发送问候”); } }

正如你所看到的,这里我没有检查演员的内部状态。相反,我观察它对我发送给它的信号的反应,并验证它是否是预期结果。

这很有道理,谢谢。所以测试一个参与者是否处于某个BENG状态的唯一方法就是查看它在该状态下是否发出某种类型的消息。基本上是的。使用“不通过共享进行通信,通过通信进行共享”座右铭,您不会直接达到参与者的状态(因为特定的参与者由于最终失败而转世,或者可能被放置在不同的机器上,并且一切都是异步的)。你可以通过它对输入信号的反应来验证它的行为。这解释了很多,谢谢。另一件事是,使用TestKit实例化参与者的一些方法之间有什么区别?例如:var actor=actorofastestactoref(“问候者”);var actor=Sys.ActorOf(“迎宾员”);var actor=Sys.ActorOf(Props.Create(),“greeter”)var actor=ActorOf(()=>new greeter(),“greeter”);所有这些都会导致相同类型的演员吗?它们有何不同?所有的
Sys.ActorOf
方法都是等效的
actorofastestactoref
将您的参与者创建为
TestActor的子参与者
是关于参与者在测试之间仍然活动的注释
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);
    }
}
var actor = Sys.ActorOf<BecomeActor>("become");