Reputation: 3
I have an actor of the following kind:
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));
}
}
When testing this actor, I expect that I will have a child actor. I'm writing the next test to check this situation (using the NUnit framework):
[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);
}
I expect that within a second I will receive the child actor on the specified path, but I get ActorNotFoundExpection.
If I'm doing something like this:
[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);
}
This works fine, but 1 of 10 times the test falls, because I get an ActorNotFoundException. But I wonder why the first option does not work the way I expect?
Am I doing something wrong?
Thanks in advance for the answer.
Upvotes: 0
Views: 215
Reputation: 7542
branchUserActor.Tell(UserBeingOnline.Create(userId, branchId));
var expectedChildActor = Sys.ActorSelection($"{actorPath}/user_{userId.AkkaPrepare()}")
.ResolveOne(TimeSpan.FromSeconds(1)).Result;
The problem here is that when you're telling UserBeingOnline
, you're triggering an asynchronous action - a message has been send to branchUserActor
, but it may not have been processed right away. In the meantime you're calling resolve one, which tells actor system to find a child of branchUserActor
- a child, which is not yet there, since the parent didn't handle the message yet.
You can use AwaitAssert(() => Assert.IsNotNull(ResolveChild())) method to work with that.
Upvotes: 1