1

我在使用 PersistAll 和 PersistAllAsync 方法的 ReceivePersistentActor 实现的某些单元测试中遇到问题。

问题是当使用 TestKit.NUnit 进行单元测试时,PersistAll/Async 调用永远不会调用它们的完成回调。然而,Persist/Async 调用工作正常,并且 PersistAll/Async 调用在单元测试之外工作正常。

这与 TestKit 以及它尝试在 CallingThreadDispatcher 上运行的方式有关吗?

我不确定如何为使用 PersistAll/Async 的代码编写单元测试 - 由于从未调用过回调(我有我的 Sender.Tell 代码),测试总是因超时而失败。

我没有做任何奇怪的事情 - 我正在使用内存日志和快照存储,它们在默认调度程序上运行(我尝试对这些使用调用线程调度程序,但在单元测试中根本没有任何工作) .

公共接口 IEvent;
公共类测试: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

    }
}
4

1 回答 1

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 等之后它突然消失了,但是一次发生的事情太多,所以不幸的是我无法为您提供一个很好的答案,确切说明我为解决它所做的工作(也是我想尝试解决这个问题并在此处重现它的原因,但我无法做到)。我希望一组完整的复制步骤以及工作项目的确切包版本可以帮助您...

于 2018-05-18T18:19:02.577 回答