2016-02-12 62 views
1

我試圖測試從測試演員發送的消息,但獲取超時異常和死信信息。 正如我使用ninject - 創建一個模擬方法,總是與探針參與者重演。 我在這裏錯過了什麼嗎?在SomethingProcessorActorTests.csakkaNet測試套件問題當測試從測試演員發送的信息

 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() :線58

[WARNING][12/02/2016 16:12:43][Thread 0009][akka://test/user/testProbe] DeadLetter from [akka://test/temp/d] 

至[阿卡://測試/用戶/ testProbe]: [ INFO] [12/02/2016 16:12:43] [Thread 0011] [akka:// test/user/testProbe] Message GetOneSomethingAndRemoveFromList from akka:// test/temp/d to akka:// test /用戶/ testProbe wa沒有交付。遇到1個死信 。 調試跟蹤: 設置探頭參考:阿卡://測試/用戶/ testProbe GetDataActorPath爲:SomethingsDataActor GetDataActorPath =>阿卡://測試/用戶/ testProbe GetDataActorPath爲:SomethingCollectorActor GetDataActorPath =>阿卡://測試/用戶/ 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

確定這樣幾件事情。

首先:您期待的類型爲:SomethingsDataActor.GetOneSomethingAndRemoveFromList。 但它看起來並不像你實際上將此消息傳遞給由testprobe表示的actorref。但很難確定,因爲你只粘貼了一半的代碼。

二:

  • 使用要求一個演員裏面被認爲是一個反模式,並可以很容易地通過採用通信更健談的風格是可以避免的。
  • 使用actor.ask()。結果更糟,因爲如果你不小心,它可能導致死鎖。 (當數據庫演員崩潰,因爲你的網絡出現故障時會發生什麼?可能沒有反應將永遠被髮回,默認詢問超時爲無窮大)

提出應該只有真正使用來自外部的演員溝通演員系統。

+0

@丹塔爾 - 感謝您的建議。 所以這是從列表中獲取項目的內部調用 - 所以我認爲應該可以正常工作。將重構,以更多的方法取代問題,然後回覆將是一種直接的行爲 - 我是對的嗎? – profesor79

+0

是的。聽起來很正確。你有沒有發現你的問題? – Danthar

+0

@Dantar - 我正在進行重構,可能很快會有更新,但是現在從請求開始轉換 - 在處理速度上得到+ 30% – profesor79

0

的問題是用嘲笑這是inhering的TestClass類,

決定爲有 「演員系統參考」

return this.Sys.ActorSelection(this.probeRef.Ref.Path); 

,但應該是:

return this.probeRef.ActorSelection(this.probeRef.Ref.Path); 

這種繼承是創造第二個獨立演員系統.....

謝謝@丹塔求救!