【问题标题】:Akka.net - Trying to test a repeated scheduled messageAkka.net - 尝试测试重复的预定消息
【发布时间】:2019-01-08 05:16:24
【问题描述】:

我正在使用 .net 核心开发 Akka.net 系统,并编写一个功能,其中一个参与者使用调度程序每 24 小时执行一个进程。

我想对此进行单元测试,但当然测试需要快速运行。我正在尝试使用 Akka.TestKit TestScheduler 来人为地提前时间,但似乎很难找到示例。我的代码适用于标准调度程序,但我无法让 TestScheduler 工作。

我已将我的流程提炼为一个简单的参与者和 2 个单元测试(参见下面的代码)。一种是使用标准调度程序成功运行的测试。另一个使用 TestScheduler 运行,但失败。演员没有收到来自 TestScheduler 的消息,我不确定我可能做错了什么或如何进一步调试。

任何帮助将不胜感激。

using System;
using System.Linq;
using Akka.Actor;
using Akka.TestKit;
using Akka.TestKit.Xunit2;
using Xunit;

namespace akkaSchedulerTest.Test
{
    // Requires Nuget Package "Akka.TestKit.Xunit2" (version 1.3.11 at the time this was written)


    public class RepeatedScheduleTest_Standard_Scheduler : TestKit
    {
        /// <summary>
        /// This test passes
        /// </summary>
        [Fact]
        public void Sender_Actor_Sends_Out_Message_Expected_Number_Of_Times()
        {
            var interval = TimeSpan.FromSeconds(1);
            var testDuration = TimeSpan.FromSeconds(2.1);
            int expectedMessageCount = 2;

            var recipientActorRef = this.TestActor;
            var messageText = "Message";

            var senderActor = Sys.ActorOf(Props.Create(() => new RepeatedMessageSenderActor(recipientActorRef, messageText, interval)));

            // verify that the other actor receives the right number of messages over the expected time
            var allExpectedMessages = Enumerable.Repeat(messageText, expectedMessageCount).ToArray();
            ExpectMsgAllOf(testDuration, allExpectedMessages);
        }
    }

    public class RepeatedScheduleTest_Test_Scheduler : TestKit
    {
        // REF: https://petabridge.com/blog/how-to-unit-test-akkadotnet-actors-akka-testkit/#how-do-i-test-scheduled-messages

        public RepeatedScheduleTest_Test_Scheduler()
            : base(@"akka.scheduler.implementation = ""Akka.TestKit.TestScheduler, Akka.TestKit""") { }

        private TestScheduler Scheduler => (TestScheduler)Sys.Scheduler;

        /// <summary>
        /// This test fails with the error:
        /// Timeout (00:00:03) while expecting 5 messages. Only got 0 after 00:00:02.9992044.
        /// In realtime it should last many hours. This is an attempt to verify the scheduled behavior in a quick test.
        /// </summary>
        [Fact]
        public void Sender_Actor_Sends_Out_Message_Expected_Number_Of_Times()
        {
            var interval = TimeSpan.FromHours(1);
            var testDuration = TimeSpan.FromHours(5.1);
            int expectedMessageCount = 5;

            var recipientActorRef = this.TestActor;
            var messageText = "Message";

            var senderActor = Sys.ActorOf(Props
                .Create(() => new RepeatedMessageSenderActor(recipientActorRef, messageText, interval))
                .WithDispatcher(CallingThreadDispatcher.Id));

            // advance the TestScheduler by enough time that the repeated messages should be processed
            Scheduler.Advance(testDuration);

            // verify that the other actor receives the right number of messages over the expected time
            var allExpectedMessages = Enumerable.Repeat(messageText, expectedMessageCount).ToArray();
            ExpectMsgAllOf(allExpectedMessages);
        }
    }

    public class RepeatedMessageSenderActor : ReceiveActor
    {
        private readonly IActorRef _recipientActorRef;
        private readonly string _messageText;
        private readonly TimeSpan _interval;

        public RepeatedMessageSenderActor(IActorRef recipientActorRef, string messageText, TimeSpan interval)
        {
            _recipientActorRef = recipientActorRef;
            _messageText = messageText;
            _interval = interval;

            Receive<SendOutMessage>(msg => HandleSendOutMessage());

            // use the scheduler to repeatedly tell this actor to send out a message at a regular interval
            Context.System.Scheduler
                .ScheduleTellRepeatedly(_interval, _interval, Self, new SendOutMessage(), Self);
        }

        /// <summary>
        /// in the failing test, this method never gets called
        /// </summary>
        private void HandleSendOutMessage()
        {
            _recipientActorRef.Tell(_messageText);
        }

        public class SendOutMessage { }
    }
}

【问题讨论】:

    标签: c# .net-core akka.net


    【解决方案1】:

    您过早地推进调度程序。在您可以安全地开始玩时间之前,您必须确保实际安排了操作。

    在这里您可以找到修复示例的一种方法https://gist.github.com/Havret/78409e91c9adf62aed3392574a3d0446

    【讨论】:

    • 还有其他方法可以确保消息被安排吗?向另一个不使用它的actor发送“Initialized”消息似乎有点武断。
    猜你喜欢
    • 1970-01-01
    • 2022-11-01
    • 2016-08-30
    • 1970-01-01
    • 2014-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-06
    相关资源
    最近更新 更多