Модульное тестирование сохраняемости Akka.NET - PersisteAll/PersistAllAsync никогда не запускается
У меня проблема в некоторых модульных тестах реализации ReceivePersistentActor с использованием методов PersistAll и PersistAllAsync.
Проблема состоит в том, что при модульном тестировании с TestKit.NUnit вызовы PersistAll/Async никогда не вызывают свои обратные вызовы завершения. Однако вызовы Persist/Async работают нормально, а вызовы PersistAll/Async работают отлично вне модульного тестирования.
Это как-то связано с TestKit и тем, как он пытается запустить что-то на CallingThreadDispatcher?
Я не уверен, как писать модульные тесты для кода, где используется PersistAll/Async - тесты всегда терпят неудачу из-за истечения времени ожидания из-за того, что обратные вызовы не вызываются (где у меня есть мой код Sender.Tell).
Я не делаю ничего странного - я использую журнал в памяти и хранилище снимков, и они работают на диспетчере по умолчанию (я пытался использовать диспетчер вызывающего потока для них, но тогда в модульных тестах ничего не работало),
открытый интерфейс IEvent;
открытый класс Test: ReceivePersistentActor {
public class StringReceivedEvent:IEvent {}
public Test()
{
Console.WriteLine("Started"); // <-- This is seen, but the next console output is not - callback is never fired
Command<string>(message => {
Console.WriteLine($"Received {message}");
PersistAll(new List<IEvent>(){new StringReceivedEvent()}, @event => {
Console.WriteLine("Persisted event"); //<-- never see this
Sender.Tell(true); //<-- this never gets called
});
});
}
public override string PersistenceId => "test-id";
}
[TestFixture]
public class Tests : Akka.TestKit.NUnit.TestKit
{
IActorRef subject;
public PublishingTests() : base(ConfigurationFactory.Load().WithFallback(Akka.TestKit.Configs.TestConfigs.DefaultConfig))
{
}
[SetUp]
public void Setup() {
subject = ActorOf(Props.Create<Test>(), "My-Test-Actor");
}
[Test]
public void Can_Persist_Event_And_Send_Completion_Reply() {
subject.Tell("hello");
ExpectMsg<bool>(TimeSpan.FromSeconds(15)); //<---- This times out
}
}
1 ответ
Я только что попробовал ваш код в новом проекте.NET Core 2.0 (с небольшими изменениями, чтобы заставить его скомпилироваться), и он отлично работает.
Вот полные шаги репликации. Сначала в командной строке /PowerShell:
mkdir akka-net-persistence-unit-testing-issue-so
cd akka-net-persistence-unit-testing-issue-so
# Install nunit template if not already done:
dotnet new -i NUnit3.DotNetNew.Template
dotnet new nunit -n TestProject
cd TestProject
dotnet add package Akka
dotnet add package Akka.Persistence
dotnet add package Akka.TestKit.Nunit
Теперь у меня есть файл.csproj, который выглядит так:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Akka" Version="1.3.7" />
<PackageReference Include="Akka.Persistence" Version="1.3.7" />
<PackageReference Include="Akka.TestKit.NUnit" Version="1.3.2" />
<PackageReference Include="nunit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.6.1" />
</ItemGroup>
</Project>
Затем, ради простого воспроизведения, я поместил весь код в один файл, например так:
using System;
using System.Collections.Generic;
using Akka.Actor;
using Akka.Configuration;
using Akka.Persistence;
using NUnit.Framework;
namespace TestProject
{
public interface IEvent {};
public class TestActor : ReceivePersistentActor
{
public class StringReceivedEvent : IEvent { }
public TestActor()
{
Console.WriteLine("Started");
Command<string>(message =>
{
Console.WriteLine($"Received {message}");
PersistAll(new List<IEvent>() { new StringReceivedEvent() }, @event =>
{
Console.WriteLine("Persisted event");
Sender.Tell(true); //<-- this is apparently getting called now!
});
});
}
public override string PersistenceId => "test-id";
}
[TestFixture]
public class PublishingTests : Akka.TestKit.NUnit.TestKit
{
IActorRef subject;
public PublishingTests() : base(ConfigurationFactory.Load().WithFallback(Akka.TestKit.Configs.TestConfigs.DefaultConfig))
{
}
[SetUp]
public void Setup()
{
subject = ActorOf(Props.Create<TestActor>(), "My-Test-Actor");
}
[Test]
public void Can_Persist_Event_And_Send_Completion_Reply()
{
subject.Tell("hello");
ExpectMsg<bool>(TimeSpan.FromSeconds(15)); //<---- This no longer times out :-)
}
}
}
Тогда вы сможете снова проверить свой код из командной строки:
dotnet test
Давать вывод:
Build started, please wait...
Build completed.
Test run for C:\Source\Privat\SoTest\akka-net-persistence-unit-testing-issue-so\TestProject\bin\Debug\netcoreapp2.0\Test
Project.dll(.NETCoreApp,Version=v2.0)
Microsoft (R) Test Execution Command Line Tool Version 15.7.0-preview-20180320-02
Copyright (c) Microsoft Corporation. All rights reserved.
Starting test execution, please wait...
Total tests: 1. Passed: 1. Failed: 0. Skipped: 0.
Test Run Successful.
Test execution time: 2,8449 Seconds
У меня была похожая проблема с UntypedPersistentActor и xUnit, но она внезапно исчезла после того, как я изменил его на ReceivePersistentActor, перезапустил Visual Studio и другие вещи, но одновременно происходило слишком много вещей, поэтому, к сожалению, я не могу дать вам хороший ответ, что именно я сделал для его решения (а также причину, по которой я хотел попытаться выяснить это и воспроизвести это здесь, но я не смог). Я надеюсь, что набор полных шагов воспроизведения с точными версиями пакета для рабочего проекта поможет вам вместо этого...