簡體   English   中英

不會立即執行的單元測試代碼

[英]Unit Testing code that doesn't execute immediately

我正在使用 C# 3.0 和 NUnit。 我想知道是否有一種標准方法可以對在一段時間后執行的代碼執行單元測試。 例如,我有一個簡單的 static class 可以注冊方法,並在 n 毫秒后調用它們。 我需要確保正在調用委托方法中的代碼。

例如,以下測試將始終通過,因為在方法退出之前沒有任何斷言。

[Test]
public void SampleTest()
{
    IntervalManager.SetTimeout(delegate{ 
        Assert.Equals(now.Millisecond + 100, DateTime.Now.Millisecond); 
    }, 100);
}

甚至可以對不立即執行的代碼進行單元測試嗎?

干杯,

保羅

那么你到底在測試什么? 你在測試定時器的工作嗎? 或者您的代碼正確設置了一個計時器,以便在到期時計時器執行回調? 在不知道代碼是什么樣子的情況下,我假設您真正想要測試的是后者。 我的回答是(1)這可能很難使用 static 方法和(2)你可能需要使用依賴注入並注入模擬計時器等,它們實際上並不運行結果方法,而是記錄通過期望您的代碼進行了正確的調用。

這個怎么樣? 它會導致測試阻塞一些預期的最大時間,以便回調觸發並在保釋之前完成,並報告錯誤。

public void Foo() {
    AutoResetEvent evt = new AutoResetEvent(false);
    Timer t = new Timer(state => {
        // Do work
        evt.Set();
    }, null, 100, Timeout.Infinite);
    if (evt.WaitOne(500)) {
        // method called and completed
    } else {
        // timed out waiting
    }
}

作為旁注。 我們通常會嘗試使用NUnit 類別標記運行緩慢的測試,並且可以選擇在某些構建上跳過這些測試。

正如其他幾個答案所表明的那樣,長時間運行的測試通常是一個壞主意。 為了便於測試這個組件,您應該考慮到您確實有兩個不同的東西要測試。

  1. 當您注冊定時委托執行時,會設置正確的時間。 這可能需要使用超時和代表數量的各種組合進行測試。
  2. 委托以適當的方式執行。

以這種方式分離測試將允許您測試您的計時機制是否按預期工作,只需少量短超時(測試您需要考慮的所有情況)。 請記住,根據系統上的當前負載以及組件代碼的復雜程度(即在IntervalManager中),在執行給定委托的實際時間中,您可能需要一點余地。

是的,像你的例子那樣做是行不通的。

相反,我建議您創建一個測試 class,用作委托,記錄調用其方法的時間和時間。

然后,您將您的模擬注入您要測試的 IntervalManager。 然后您的測試方法必須等待 IntervalManager(使用 IntervalManager 提供的合適方法,或者等待幾秒鍾),然后您可以驗證測試 class 的 state。

順便說一句,這種方法通常被稱為mocking 在這種情況下,測試 class 將是模擬 object。

也許我遺漏了一些東西,但 Visual Studio 的單元測試具有特殊屬性,您可以將其放在控制執行順序和其他內容的方法上。 這應該在您第一次制作單元測試項目時自動生成:

    #region Additional test attributes
    // 
    //You can use the following additional attributes as you write your tests:
    //
    //Use ClassInitialize to run code before running the first test in the class
    //[ClassInitialize]
    //public static void MyClassInitialize(TestContext testContext) {
    //}
    //
    //Use ClassCleanup to run code after all tests in a class have run
    //[ClassCleanup()]
    //public static void MyClassCleanup()
    //{
    //}
    //
    //Use TestInitialize to run code before running each test
    //[TestInitialize()]
    //public void MyTestInitialize()
    //{
    //}
    //
    //Use TestCleanup to run code after each test has run
    //[TestCleanup()]
    //public void MyTestCleanup()
    //{
    //}
    //
    #endregion

因此,使用 [ClassInitialize] 應該允許您將必須首先執行的任何內容寫入方法中。 然后你的測試就可以運行了。 或者您可以使用 [TestInitialize] 在每次測試之前運行代碼。

當然你可以測試一下。 你只需要等待它執行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM