我有一个使用MVVM模式的WPF项目。
在特定的视图模型中,我使用后台任务(Task类)定期填充ObservableCollection。
我使用下面的代码来实际填充集合:
private void InitialiseAssignablePermissions()
{
var assignablePermissions = DetermineAssignablePermissions();
CurrentDispatcher.Invoke(() =>
{
foreach (var ap in assignablePermissions)
{
AssignablePermissions.Add(ap);
}
});
}
这非常有效,我的单元测试运行愉快,并且都变绿了。
但是,如果我有一个ICollectionView连接到ObservableCollection,当我运行测试时,我得到一个跨线程异常,测试失败。当我第一次尝试将项添加到集合时会发生异常。当项目执行时,代码仍然可以很愉快地运行。我需要集合视图,因为我想过滤项目。
例外是:
This type of CollectionView does not support changes to its
SourceCollection from a thread different from the Dispatcher thread.
CurrentDispatcher类是我为单元测试添加的一个简单类:
internal static class CurrentDispatcher
{
internal static void Invoke(Action action)
{
if (App.Current != null)
App.Current.Dispatcher.Invoke(action);
else
action();
}
}
如何添加集合视图并进行单元测试?
答案 0 :(得分:0)
在为WPF项目编写测试时遇到了同样的问题。问题是当您在运行测试项目时调用invoke时,您的调度程序未运行。
您可以通过在单独的线程上运行调度程序来解决此问题。您可能会注意到,错误时会显示错误的堆栈跟踪,因此我不会重新抛出从调度程序收到的未处理异常,而是调用assert.fail并将堆栈跟踪附加到错误消息中。如果有人知道更好的方法来解决这个问题,请告诉我。
以下是我最终使用的代码:
public static void RunTestInDispatcher(Action action)
{
failException = null;
GetDispatcher().Invoke(action);
if (failException != null)
{
Assert.Fail(string.Format("{0}\n{1}", failException.Message, failException.StackTrace));
}
}
private static object dispatcherLock = new object();
private static Dispatcher dispatcher = null;
public static Dispatcher GetDispatcher()
{
lock (dispatcherLock)
{
if (dispatcher == null)
{
Thread t = new Thread(new ThreadStart(() =>
{
lock (dispatcherLock)
{
dispatcher = Dispatcher.CurrentDispatcher;
dispatcher.UnhandledException += new DispatcherUnhandledExceptionEventHandler(dispatcher_UnhandledException);
Monitor.Pulse(dispatcherLock);
}
Dispatcher.Run();
}));
t.SetApartmentState(ApartmentState.STA);
t.Start();
Monitor.Wait(dispatcherLock);
}
}
return dispatcher;
}
static Exception failException = null;
static void dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
failException = e.Exception;
}