Некоторые проблемы с тестированием Akka.net

  • Версия Akka.NET v1.3.8
  • Версия Akka.TestKit.NUnit3 v1.3.2
  • Версия NUnit v3.10.1
  • Платформа Windows 10

У меня есть такой актер:

public class BranchUsersActor : ReceiveActor
{
    public BranchUsersActor()
    {
        Receive<UserBeingOnline>((online) =>
        {
            var userActorName = $"user_{online.UserId}";
            if (Context.Child(userActorName).Equals(ActorRefs.Nobody))
            {                
                var user = Context.ActorOf(UserActor.Props(online.UserId, online.BranchId), userActorName);
                user.Tell(online);                    
            }
        });
    }

    public static Props Props(LoggingTags tags)
    {
        return Akka.Actor.Props.Create(() => new BranchUsersActor(tags));
    }
}

При тестировании этого актера я рассчитываю, что у меня будет ребенок-актер. Я пишу следующий тест, чтобы проверить эту ситуацию (с использованием фреймворка NUnit):

[Test]
public void Test()
{
    var branchUserActor = Sys.ActorOf(BranchUsersActor.Props());
    branchUserActor.Tell(UserBeingOnline.Create(userId, branchId));

    var expectedChildActor = Sys.ActorSelection($"{actorPath}/user_{userId.AkkaPrepare()}")
        .ResolveOne(TimeSpan.FromSeconds(1)).Result;

    Assert.IsNotNull(expectedChildActor);
}

Я ожидаю, что через секунду я получу дочерний субъект по указанному пути, но получаю ActorNotFoundExpection.

Если я делаю что-то вроде этого:

[Test]
public void Test()
{
    var branchUserActor = Sys.ActorOf(BranchUsersActor.Props());
    branchUserActor.Tell(UserBeingOnline.Create(userId, branchId));

    Task.Delay(100).ContinueWith(_ => 
    {
        var expectedChildActor = Sys.ActorSelection($"{actorPath}/user_{userId.AkkaPrepare()}")`enter code here`
            .ResolveOne(TimeSpan.FromSeconds(1)).Result;
    }
    Assert.IsNotNull(expectedChildActor);    
}

Это работает нормально, но в 1 из 10 раз тест не выполняется, потому что я получаю ActorNotFoundException. Но мне интересно, почему первый вариант не работает так, как я ожидал?

Я делаю что-то неправильно?

Заранее спасибо за ответ.


person Vladimir Luzhin    schedule 13.07.2018    source источник


Ответы (1)


branchUserActor.Tell(UserBeingOnline.Create(userId, branchId));

var expectedChildActor = Sys.ActorSelection($"{actorPath}/user_{userId.AkkaPrepare()}")
  .ResolveOne(TimeSpan.FromSeconds(1)).Result;

Проблема здесь в том, что когда вы сообщаете UserBeingOnline, вы запускаете асинхронное действие - сообщение было отправлено на branchUserActor, но оно могло быть обработано не сразу. Тем временем вы вызываете команду resolve one, которая сообщает системе акторов найти дочерний элемент branchUserActor - дочерний элемент, которого еще нет, поскольку родитель еще не обработал сообщение.

Вы можете использовать AwaitAssert (() => Assert.IsNotNull (ResolveChild ())), чтобы с этим работать.

person Bartosz Sypytkowski    schedule 13.07.2018