2015-04-22 103 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);