问题
I was trying to test message sent from tested actor, but getting timeout exception and a Dead letter info. As I am using ninject - created a mock method which always replays with probe actor reference. Am I missing something here?
Assert.Fail failed. Failed: Timeout 00:00:03 while waiting for a message of type System.Type at Akka.TestKit.TestKitBase.InternalExpectMsgEnvelope(Nullable`1 timeout, Action`2 assert, String hint, Boolean shouldLog) at Akka.TestKit.TestKitBase.InternalExpectMsgEnvelope(Nullable`1 timeout, Action`1 msgAssert, Action`1 senderAssert, String hint) at Akka.TestKit.TestKitBase.InternalExpectMsg(Nullable`1 timeout, Action`1 msgAssert, String hint) at Akka.TestKit.TestKitBase.ExpectMsg(T message, Nullable`1 timeout, String hint) at
AutoApply.UnitTests.SomethingProcessorActors.SomethingProcessorActorTests.SomethingProcessorActorWhenMergeDataAndGetsNoProfilesLogsThat() in SomethingProcessorActorTests.cs: line 58
[WARNING][12/02/2016 16:12:43][Thread 0009][akka://test/user/testProbe] DeadLetter from [akka://test/temp/d]
to [akka://test/user/testProbe]: [INFO][12/02/2016 16:12:43][Thread 0011][akka://test/user/testProbe] Message GetOneSomethingAndRemoveFromList from akka://test/temp/d to akka://test/user/testProbe was not delivered. 1 dead letters encountered. Debug Trace: Setting probe reference: akka://test/user/testProbe GetDataActorPath for:SomethingsDataActor GetDataActorPath =>akka://test/user/testProbe GetDataActorPath for:SomethingCollectorActor GetDataActorPath =>akka://test/user/testProbe
[TestClass]
public class SomethingProcessorActorTests : TestKit
{
/// <summary>The factory helper</summary>
private IMockingExtension factoryHelper;
private TestProbe probeActorRef;
/// <summary>Configurations this instance.</summary>
[TestInitialize]
public void Config()
{
this.probeActorRef = this.CreateTestProbe("testProbe");
this.factoryHelper = new MockingFactoryHelper();
this.factoryHelper.SetProbe(this.probeActorRef.TestActor);
}
/// <summary>Somethings the processor actor when merge data and gets no profiles logs that.</summary>
[TestMethod]
public void SomethingProcessorActorWhenMergeDataAndGetsNoProfilesLogsThat()
{
// arrange
var actor =
this.Sys.ActorOf(
Props.Create(() => new SomethingProcessorActor(this.factoryHelper as IActorPathAndFactory)),
"SomethingActor");
// act
actor.Tell(new SomethingProcessorActor.ProcessSomethings());
// assert
this.probeActorRef.ExpectMsgFrom<SomethingsDataActor.GetOneSomethingAndRemoveFromList>(actor, new TimeSpan(0, 0, 0, 5));
}
}
=======================
public partial class SomethingProcessorActor : ReceiveActor
{
/// <summary>The helper</summary>
private readonly IActorPathAndFactory helper;
/// <summary>The log</summary>
private readonly ILoggingAdapter log = Context.GetLogger();
/// <summary>The vote execution profile</summary>
private List<SomethingProcessingObject> voteExecutionProfile = new List<SomethingProcessingObject>();
/// <summary>
/// Initializes a new instance of the <see cref="SomethingProcessorActor"/> class.
/// </summary>
/// <param name="helper">
/// The helper.
/// </param>
public SomethingProcessorActor(IActorPathAndFactory helper)
{
this.helper = helper;
this.Receive<ProcessSomethings>(
x =>
{
this.log.Debug("Received: ProcessSomethings");
this.BecomeStacked(this.Working);
this.RetriveSomethingAndPushForProcessing();
});
}
/// <summary>Supervisors strategy.</summary>
/// <returns>Supervisors strategy for that actor</returns>
protected override SupervisorStrategy SupervisorStrategy()
{
return new AllForOneStrategy(10, 3000, Decider.From(x => Directive.Stop));
}
/// <summary>
/// The merge data.
/// </summary>
private void RetriveSomethingAndPushForProcessing()
{
this.log.Debug($"Processing Somethings...");
var SomethingActor1 = this.helper.GetActorPath(ActorsEnum.SomethingsDataActor);
var SomethingActor2 = this.helper.GetActorPath(ActorsEnum.SomethingCollectorActor);
var something = (SomethingDto)SomethingActor1.Ask(new SomethingsDataActor.GetOneSomethingAndRemoveFromList()).Result;
while (Something.SomethingId>0)
{
this.log.Debug($"Sending data to SomethingCollector with Something id: {Something.SomethingId}");
SomethingActor2.Tell(new SomethingCollectorActor.ProcessSomethingDto(Something));
Something = (SomethingDto)SomethingActor1.Ask(new SomethingsDataActor.GetOneSomethingAndRemoveFromList()).Result;
}
this.log.Debug("Sending data to SomethingCollector -- ALL SENT");
this.UnbecomeStacked();
}
The mock objects just send probe actor as per every request
public ActorSelection GetActorPath(ActorsEnum actorsEnum)
{
Debug.WriteLine("GetDataActorPath for:" + actorsEnum);
Debug.WriteLine("GetDataActorPath =>" + this.probeRef.Path);
return this.Sys.ActorSelection(this.probeRef.Path);
}
public void SetProbe(IActorRef actorRef)
{
Debug.WriteLine("Setting probe reference: " + actorRef.Path);
this.probeRef = actorRef;
}
ignition overview
回答1:
Ok so a few things.
First of all: You are expecting on a message of the type: SomethingsDataActor.GetOneSomethingAndRemoveFromList
.
But it doesn't look like you are actually passing this message to an actorref that is represented by the testprobe. But its hard to be sure since you only pasted halve the code.
Second:
- Using ask inside an actor is considered an anti pattern, and can easily be avoided by employing a more conversationalist style of communication.
- Using actor.ask().Result is even worse because it can lead to deadlocks if your not carefull. (what happens when the database actor crashes because your network is down? potentially no response will ever be send back and the default Ask timeout is infinite)
Ask should only really be used to communicate with an actor from outside the actor system.
回答2:
The problem was with mocking class that was inhering TestClass,
decided for that to have "Actor System Reference"
return this.Sys.ActorSelection(this.probeRef.Ref.Path);
but should be:
return this.probeRef.ActorSelection(this.probeRef.Ref.Path);
This inheritance was creating a second independednt actor system.....
Thanks @Dantar for help!
来源:https://stackoverflow.com/questions/35367570/akkanet-test-kit-issue-when-testing-messges-sent-from-tested-actor