我有UserControl
在EventAggregator
事件中发布Loaded
条消息。为了测试这个(并引发Loaded
事件)我正在创建一个窗口并向其添加控件,然后等待引发Loaded
事件。
有没有办法设置测试以便Loaded
事件触发而无需创建控件并将其添加到窗口?
例如:
[Test, RequiresSTA]
public void active_thingy_message_is_published_on_loaded()
{
const string TestMsg = "Active thingy changed";
using (AutoResetEvent loadedEvent = new AutoResetEvent(false))
{
DummyEventService eventService = new DummyEventService();
DummyControl control = new DummyControl(eventService, TestMsg);
control.Loaded += delegate { loadedEvent.Set(); };
Assert.That(eventService.Message, Is.Null, "Before.");
Window window = new Window { Content = control };
window.Show();
loadedEvent.WaitOne();
window.Dispatcher.InvokeShutdown();
Assert.That(eventService.Message, Is.EqualTo(TestMsg), "After.");
}
}
private class DummyControl : UserControl
{
public DummyControl(DummyEventService eventService, string testMsg)
{
Loaded += delegate { eventService.Publish(testMsg); };
}
}
private class DummyEventService
{
public string Message { get; private set; }
public void Publish(string msg) { Message = msg; }
}
更新
我已将标题从“单元测试...”更改为“测试...”,并将标记“单元测试”替换为“测试”。
我宁愿不分开究竟是什么类别的测试,因为它不具有建设性。是的,可以说这不是“单元测试”,但这没有用。我想测试一个依赖于控件生命周期的问题,这涉及Loaded
事件。这是一个重要的回归测试,因为我无法控制的第三方组件取决于Loaded
处提出的消息。
可以在不将控件添加到窗口的情况下引发Loaded
事件吗?
答案 0 :(得分:7)
如果您只是想触发目标控件的Loaded事件,那么Reflection应该可以解决这个问题。
public static void RaiseLoadedEvent(FrameworkElement element)
{
MethodInfo eventMethod = typeof(FrameworkElement).GetMethod("OnLoaded",
BindingFlags.Instance | BindingFlags.NonPublic);
RoutedEventArgs args = new RoutedEventArgs(FrameworkElement.LoadedEvent);
eventMethod.Invoke(element, new object[] { args });
}
这实际上触发了每个FrameworkElement中存在的OnLoaded方法,因此如果您的测试需要Application状态,那么这将无效。
此外,父母的Loaded事件与其子女之间没有任何关系。如果测试需要子元素触发其Loaded事件,那么helper方法将需要手动遍历子控件并触发它们。
答案 1 :(得分:7)
在过去的两年里,事情可能发生了变化。为了代码覆盖,我也遇到了这个问题,这是解决方案。
WPF UIElements继承了一个名为RaiseEvent的方法,该方法采用RoutedEventArgs。这可以使用特定的UIElement的.LoadedEvent构建,允许您获得代码覆盖的最后一位。
我怀疑你仍然需要我的答案,但有人可能。
答案 2 :(得分:5)
将Loaded
事件处理程序中的内容重构为自己的方法,并让Loaded
事件处理程序调用它。编写单元测试以测试重构方法,而不是Loaded
事件。
单元测试正在验证一个单元是否完成它应该做的事情。测试单元如何与其他单元互操作是集成测试。进行集成测试以及能够对集成单元进行回归测试当然很有价值,但这与单元测试不同。
最后:如果您无法确信控件的Loaded
事件在加载时被触发(这是您进行此类集成测试的主要原因),那么这是非常错误的,您应该调查一下。