2011-02-28 68 views
3

我正在寫一個客戶端,它每秒發送一個「心跳信號」給服務器。客戶端在後臺線程中調用WCF服務來報告其活動。如何測試心跳模式?

如何對此進行單元測試?我是否需要等待幾秒鐘,並檢查是否多次調用適當的方法?

它應該是某種場景測試嗎?也許我不應該擔心在整個客戶生命週期中不斷調用服務?

我可以測試單個呼叫到WCF服務,但它不測試「心跳模式」。

我正在使用TDD方法。 (C#,NUnit,Moq)

任何建議或例子?

編輯:

我認爲這是不夠清晰。

這是什麼,我有一個更簡單的版本:

public class FeedService 
{ 
    private Timer t; 

    public FeedService() 
    { 
     t.Interval = 1000; 
     t.Elapsed += TimerElapsed; 
     t.Start(); 
    } 

    private void TimerElapsed(object sender, ElapsedEventArgs e) 
    { 
     t.Stop(); 
     SendHeartbeat(); 
     t.Start(); 
    } 
} 

...這是我的測試:

[Test] 
public void Heartbeat_called_twice_after_2_seconds() 
{ 
    var mockFeedService = new Mock<FeedService>(); 

    Thread.Sleep(2000); 
    mockFeedService.Verify(x => x.SendHeartBeat(), Times.AtLeast(2)); 
} 

我有兩個問題:
1)爲什麼我的測試總是失敗?我做錯了什麼?
2)我應該測試它嗎?

回答

5

您希望測試的功能必須先隔離。例如,在這種情況下,可以測試兩個方面。一個是,listenbeat組件實際上在指定的時間表上發送心跳消息。另一個是服務收到消息。如果您抽象服務,那麼您可以在服務實現中獨立地測試hearbeat組件。這可以在單元測試中完成,方法是啓動hearbeat組件,然後休眠,然後驗證存根或模擬服務實現接收到預期的消息數量。確保服務正在接收消息的測試是integration test,因此不是「純」的單元測試。但是,由於無論如何都必須進行測試,因此您可以爲此測試一下。

+0

非常感謝。我不在乎WCF服務是否正在接收消息。我需要測試的是我的客戶端每秒發送消息而不會收到任何錯誤的能力。我使用模擬服務測試了對WCF服務的「手動」調用,但這並不是我想要實現的。方法「SendHeartbeat」應該是私有的,應該在TimerElapsed中調用。 – Novitzky

2

我會在「網關」類型的類中包裝與服務的交互。這可以由您的測試中的模擬替換,並且模擬可以計算您所做的調用或您可能需要的任何統計信息。

問候, 莫滕

+0

要清楚;這個解決方案是部分refac(包裝),部分測試,部分模擬,但是你可能會發現,在一個更容易測試的解決方案中運行,也將證明是一個更強大的設計。 – Morten

0

要測試的方案是,嚴格來說,集成測試。

我已經採取了類似的試驗,施工場景的方法是使用這個方便的功能:

/// <summary> 
/// Wait no longer than @waitNoLongerThanMillis for @thatWhatWeAreWaitingFor to return true. 
/// Tests every second for the 
/// </summary> 
/// <param name="thatWhatWeAreWaitingFor">Function that when evaluated returns true if the state we are waiting for has been reached.</param> 
/// <param name="waitNoLongerThanMillis">Max time to wait in milliseconds</param> 
/// <param name="checkEveryMillis">How often to check for @thatWhatWeAreWaitingFor</param> 
/// <returns></returns> 
private bool WaitFor(Func<bool> thatWhatWeAreWaitingFor, int checkEveryMillis, int waitNoLongerThanMillis) 
{ 
    var waitedFor = 0; 
    while (waitedFor < waitNoLongerThanMillis) 
    { 
     if (thatWhatWeAreWaitingFor()) return true; 

     Console.WriteLine("Waiting another {0}ms for a situation to occur. Giving up in {1}ms ...", checkEveryMillis, (waitNoLongerThanMillis - waitedFor)); 
     Thread.Sleep(checkEveryMillis); 
     waitedFor += checkEveryMillis; 
    } 
    return false; 
} 

用法:因爲.NET4但

// WaitFor (transaction to become failed, checkEverySoOften, waitNoLongerThan) 
int wait = (Settings.EventHandlerCoordinatorNoActivitySleepTime + 5) * 1000; 
var failedEventExists = WaitFor(() => EventQueueManager.GetFailedEvents(0, 10).TotalRecords > 0, checkEveryMillis: 1000, waitNoLongerThanMillis: wait); 

if (!failedEventExists) 
    Assert.Fail("Waited longer than " + wait + " without any evidence of the event having been handled. Expected to failed event on the queue."); 

它使用C#功能僅適用這些日子可能適合大多數.Net開發者。