2014-10-20 78 views
0

我編寫了一個測試(NUnit)來測試我的Amazon SES電子郵件發送功能,該功能應該在我的Amazon SQS隊列中生成一個退回通知。我在一個新線程上輪詢該隊列1分鐘,等待並驗證退回通知。多線程單元測試 - 通知調用事件線程以停止睡眠

我想增加幾分鐘時間以確保我不會錯過它。然而,響應可能在幾秒鐘內發生,在這種情況下,我只想記錄它花了多長時間並完成測試,因爲一旦驗證收據就沒有必要繼續等待。

我該如何以一種乾淨的方式完成這個線程場景,並且我的意思是沒有污染MethodInMainApp()和測試代碼。在主應用程序中這不應該發生(它應該繼續無限期地進行輪詢),它只應該在測試前停止。我應該從兩個入口點傳遞ThreadStart函數,但是這並不回答我問的問題。

[Test] 
    public async void SendAndLogBounceEmailNotification() 
    { 

     Thread bouncesThread = Startup.MethodInMainApp(); 
     bouncesThread.Start(); 

     bool success = await _emailService.SendAsync(...); 

     Assert.AreEqual(success, true); 

     //Sleep this thread for 1 minute while the 
     //bouncesThread polls for bounce notifications 
     Thread.Sleep(60000); 
    } 


    public static Thread MethodInMainApp() 
    { 
     ... 


     Thread bouncesThread = new Thread(() => 
     { 
      while (true) 
      { 
       ReceiveMessageResponse receiveMessageResponse = sqsBouncesClient.ReceiveMessage(bouncesQueueRequest); 
       if(receiveMessageResponse.Messages.Count > 0) 
       { 
        ProcessQueuedBounce(receiveMessageResponse); 
        //done for test 
       }      
      } 
     }); 

     bouncesThread.SetApartmentState(ApartmentState.STA); 
     return bouncesThread; 
    } 

回答

1

使用Monitor類。要信號線程繼續

lock (_lockObject) 
{ 
    Monitor.Wait(_lockObject, 60000); 
} 

然後:

lock (_lockObject) 
{ 
    Monitor.Pulse(_lockObject); 
} 

當然,這需要在類中添加static readonly object _lockObject = new object()地方

相反的Thread.Sleep(60000),使用此。

我並不是說整體策略實際上是正確的方法。看起來像這裏,單元測試方法更好地顯式調用其他正在執行工作來等待並驗證響應的方法。但上述應該解決您的具體問題。

+0

嘿謝謝,但我得到錯誤「對象同步方法是從一個非同步的代碼塊調用」。我在測試類上創建了lockobject,並將其作爲可選參數傳遞給我的方法。這樣,我可以忽略它,當它不是一個測試,只是如果(lockobject!= null)Monitor.Pulse(lockobject);該行引發錯誤 – parliament 2014-10-20 20:02:59

+0

如錯誤消息所示,您正在調用Monitor.Pulse(),而沒有先取得該對象的鎖定。如果你想讓它成爲可選的,那很好。但在允許調用Monitor.Pulse()之前,您仍然需要「鎖定(lockobject)」。 – 2014-10-20 21:49:51