Akka.net - Попытка проверить повторное запланированное сообщение - PullRequest
0 голосов
/ 08 января 2019

Я работаю в системе Akka.net с использованием ядра .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 { }
    }
}

1 Ответ

0 голосов
/ 11 января 2019

Вы продвигаете свой планировщик слишком рано. Прежде чем вы сможете безопасно начать играть со временем, вы должны быть уверены, что операция действительно запланирована.

Здесь вы можете найти один из способов исправления вашего примера https://gist.github.com/Havret/78409e91c9adf62aed3392574a3d0446

...