2015-04-22 100 views
1

我有一個WPF用戶控件,我正在寫一些使用NUnit的單元測試。其中一個測試在窗口上顯示控件,並單擊控件上的按鈕。之後,它看起來確認收到了正確的結果。在NUnit測試IInvokeProvider.Invoke

使用RaisedEvents它看起來像這樣,並正常工作。

MyButton.RaiseEvent(buttonArgs); 
Assert.AreEqual(expected, actual); 

我想使用自動化框架來做同樣的事情。喜歡的東西:

ButtonAutomationPeer peer = new ButtonAutomationPeer(MyButton); 
IInvokeProvider invokeProv = (IInvokeProvider)(peer.GetPattern(PatternInterface.Invoke)); 
invokeProv.Invoke(); 
Assert.AreEqual(expected, actual); 

現在,在這種情況下,斷言失敗(如預期),因爲調用是異步調用,並在聲明的時間尚未發生。

我希望我可以通過在單獨的線程上調用Invoke並等待它完成來解決此問題。

Thread thread = new Thread(invokeProv.Invoke); 
thread.Start(); 
thread.Join(); 

但是,這仍然失敗。由於不只是在睡覺:

invokeProv.Invoke(); 
Thread.Sleep(1000); 

顯示一個對話框,並迫使用戶繼續,但是不工作。

invokeProv.Invoke(); 
System.Windows.MessageBox.Show(""); 

所以我認爲我需要做某種設置來讓事情按照我喜歡的方式行事。也許爲調度程序或窗口設置一個單獨的線程。我確信有這方面的例子,但我似乎沒有在正確的關鍵詞搜索。請注意,NUnit要求我使用RequiresSTA屬性運行我的單元測試。

+0

@mikez這做到了。謝謝。 – denver

+0

好的,我將作爲回答發佈。 –

回答

2

我認爲你的結論是正確的。 IInvokeProvider.Invoke是異步方式,Dispatcher.BeginInvoke是異步方式。它只是將一條消息放入隊列中供調度員處理。但是,在顯示消息框之前,您並未啓動線程的調度程序。您可能想要this之類的東西來處理測試線程中的調度程序操作。

public static void DoEvents() 
{ 
    DispatcherFrame frame = new DispatcherFrame(); 
    Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, 
      new DispatcherOperationCallback(ExitFrame), frame); 
    Dispatcher.PushFrame(frame); 
} 

public static object ExitFrame(object f) 
{ 
    ((DispatcherFrame)f).Continue = false; 
    return null; 
} 

哪位能像這樣被使用:

ButtonAutomationPeer peer = new ButtonAutomationPeer(MyButton); 
IInvokeProvider invokeProv = (IInvokeProvider)(peer.GetPattern(PatternInterface.Invoke)); 
invokeProv.Invoke(); 
DoEvents(); 
Assert.AreEqual(expected, actual);