akkaNet test kit issue when testing messges sent from tested actor

六眼飞鱼酱① 提交于 2019-12-11 10:25:37

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!