2009-09-28 52 views
6

我正在編寫一個單元測試套件來測試TCP/IP通信庫。如何在單元測試中處理後臺線程中的異常?

由於我使用BeginAcceptClient和EndAcceptClient,消息在後臺線程中接收。

收到消息後,我對它執行了一些斷言,但是如果斷言失敗,VSTestHost.exe崩潰。

我搜索了一下,發現它的事實是Assert異常在後臺線程中被拋出。

編輯:我在做什麼的樣本代碼,只是爲了ilustrate:


public void TestFooMessage() { 
    Server.OnReceive += (s, e) => { 
     Assert.IsInstanceOfType(e.Message, typeof(Foo)); 
    }; 

    var message = new Foo(); 
    Client.Send(message); 
} 

有誰知道如何使它按預期工作:記錄斷言並繼續運行正常?

回答

6

你不應該寫的聲明在後臺線程(比如:後臺事件處理程序),因爲測試框架無法處理這個問題。你應該只收集那裏的價值。您可以使用AutoResetEvents例如同步主線程。將值寫入字段,斷言主線程中的字段。

如果郵件從未進入,則需要超時。

有點僞代碼(實際上不是僞):

private AutoResetEvent ReceiveEvent = new AutoResetEvent(false); 
private EventArgs args; 
private bool ReceiveCalled = false; 

// event handler with some argument 
private void Receive(object sender, EventArgs args) 
{ 
    // get some arguments from the system under test 
    this.args= args; 

    // set the boolean that the message came in 
    ReceiveCalled = true; 

    // let the main thread proceed 
    ReceiveEvent.Set(); 
} 

[TestMethod] 
public void Test() 
{ 
    // register handler 
    Server.OnReceive += Receive; 

    var message = new Foo(); 
    Client.Send(message); 

    // wait one second for the messages to come in 
    ReceiveEvent.WaitOne(1000); 

    // check if the message has been received 
    Assert.IsTrue(
    ReceiveCalled, 
    "AcceptClientReceived has not been called"); 

    // assert values from the message 
    Assert.IsInstanceOfType(args.Message, typeof(Foo))  
} 

順便說一句:你還是可以寫的處理程序作爲一個lambda表達式,即使只使用局部變量避免領域。但如果一切都是單一的方法,可能會更難閱讀。

1

我懷疑你基本上需要某種形式的「一切都好」標誌:

  1. 創建這個全局標誌,並在測試
  2. 開始設置爲True撰寫平行Assert方法這會清除標誌並可能爲「原因」設置另一個變量(或將其添加到列表中),然後乾淨地退出線程(如果可能)
  3. 使主測試線程等待所有其他線程完成,然後檢查國旗。

這有可能是一些測試框架已經建成這樣的,但我不知道任何副手的...

+1

問題是線程是由被測系統創建的。你通常甚至不知道他們,除非你被回電話。單元測試中沒有通用的後臺線程解決方案。 – 2009-09-28 19:39:45

+1

等待測試函數中的事件,並在異步回調中設置事件。 – 2009-09-28 19:53:43

0

我試了一下斯特凡建議和下面的工作對我來說:

public void TestFooMessage() { 
    Foo message = null; 
    var resetEvent = new AutoResetEvent(false); 

    Server.OnReceive += (s, e) => { 
     message = e.Message; 
     resetEvent.Set(); 
    }; 

    var message = new Foo(); 
    Client.Send(message); 

    if (resetEvent.WaitOne(1000)) { 
     Assert.IsInstanceOfType(e.Message, typeof(Foo)); 
    } else { 
     Assert.Fail("Foo not received!"); 
    } 
} 

謝謝!

相關問題