Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 针对WPF和Dispatcher的NMock问题测试_C#_Wpf_Testing_Dispatcher_Nmock - Fatal编程技术网

C# 针对WPF和Dispatcher的NMock问题测试

C# 针对WPF和Dispatcher的NMock问题测试,c#,wpf,testing,dispatcher,nmock,C#,Wpf,Testing,Dispatcher,Nmock,这里有一个是给那些穿线的瘾君子的。我有这个方法: public void RefreshMelts() { MeltsAvailable.Clear(); ThreadPool.QueueUserWorkItem(delegate { Dispatcher.BeginInvoke((ThreadStart)delegate { eventAggrega

这里有一个是给那些穿线的瘾君子的。我有这个方法:

    public void RefreshMelts()
    {
        MeltsAvailable.Clear();

        ThreadPool.QueueUserWorkItem(delegate
        {
            Dispatcher.BeginInvoke((ThreadStart)delegate
            {
                eventAggregator.GetEvent<BusyEvent>().Publish(true);
                eventAggregator.GetEvent<StatusMessageEvent>().Publish(
                    new StatusMessage("Loading melts...", MessageSeverity.Low));
            });

            try
            {
                IList<MeltDto> meltDtos = meltingAppService.GetActiveMelts();

                Dispatcher.Invoke((ThreadStart)delegate
                {
                    foreach (MeltDto availableMelt in meltDtos)
                    {
                        MeltsAvailable.Add(availableMelt);
                    }
                    OnPropertyChanged("MeltsAvailable");

                    eventAggregator.GetEvent<BusyEvent>().Publish(false);
                    eventAggregator.GetEvent<StatusMessageEvent>().Publish(
                        new StatusMessage("Melts loaded", MessageSeverity.Low));
                });
            }
            catch (ApplicationException ex)
            {
                log.Error("An error occurred in MeltsViewModel when attempting to load melts", ex);

                Dispatcher.Invoke((ThreadStart)delegate
                {
                    MeltsAvailable.Clear();

                    eventAggregator.GetEvent<StatusMessageEvent>().Publish(
                        new StatusMessage("Melt data could not be loaded because an error occurred; " +
                            "see the application log for detail",
                            MessageSeverity.High));
                    eventAggregator.GetEvent<BusyEvent>().Publish(false);
                });
            }

        });

    }
public void refreshMels()
{
meltsavable.Clear();
ThreadPool.QueueUserWorkItem(委托
{
Dispatcher.BeginInvoke((ThreadStart)委托
{
eventAggregator.GetEvent().Publish(true);
eventAggregator.GetEvent().Publish(
新状态消息(“正在加载融化…”,消息严重性.Low));
});
尝试
{
IList meltDtos=meltingAppService.getActiveMels();
Dispatcher.Invoke((ThreadStart)委托
{
foreach(熔接至可用熔接至熔接至)
{
熔化可用。添加(可用熔化);
}
不动产变更(“MELTSAVALIABLE”);
eventAggregator.GetEvent().Publish(false);
eventAggregator.GetEvent().Publish(
新的StatusMessage(“已加载”,MessageSeverity.Low));
});
}
捕获(ApplicationException ex)
{
log.Error(“尝试加载熔体时MeltsViewModel中发生错误”,例如);
Dispatcher.Invoke((ThreadStart)委托
{
meltsavable.Clear();
eventAggregator.GetEvent().Publish(
new StatusMessage(“由于发生错误,无法加载熔化数据;”+
“有关详细信息,请参阅应用程序日志”,
严重程度高),;
eventAggregator.GetEvent().Publish(false);
});
}
});
}
这是在WPF用户控件中定义的。MELTSAVIABLE是一种可观察到的MELTDTO集合。这段代码在应用程序本身中运行时效果很好

问题是,我想使用NMock创建一个单元测试,以验证此方法的结果——特别是,一旦调用了它,MeltsAvailable属性就会有一些项。以下是测试方法:

    [TestMethod]
    public void GetAvailableMeltsTest()
    {
        MeltDto mockMelt1 = new MeltDto();
        MeltDto mockMelt2 = new MeltDto();

        mockMelt1.MeltIdentifier = "TST0001";
        mockMelt2.MeltIdentifier = "TST0002";

        IList<MeltDto> availableMelts = new List<MeltDto>();
        availableMelts.Add(mockMelt1);
        availableMelts.Add(mockMelt2);

        Expect.Exactly(1).On(service).Method("GetActiveMelts").Will(Return.Value(availableMelts));


        MeltsViewModel vm = new MeltsViewModel(aggregator, logger, service, configManagerFactory); // All of these are mock objects

        vm.RefreshMelts();
        Thread.Sleep(millisecondDelayForEventPublish * 100);

        mockery.VerifyAllExpectationsHaveBeenMet();

        Assert.AreEqual(vm.MeltsAvailable.Count, 2);
        Assert.AreEqual(vm.MeltsAvailable[0].MeltIdentifier, "TST0001");
        Assert.AreEqual(vm.MeltsAvailable[1].MeltIdentifier, "TST0002");

    }
[TestMethod]
public void GetAvailableMeltsTest()
{
MeltDto mockMelt1=新的MeltDto();
MeltDto mockMelt2=新的MeltDto();
mockMelt1.MeltIdentifier=“TST0001”;
mockMelt2.MeltIdentifier=“TST0002”;
IList availableMelts=新列表();
添加(mockMelt1);
添加(mockMelt2);
Expect.justice(1).On(service.Method)(“GetActiveMels”).Will(Return.Value(availableMelts));
MeltsViewModel vm=新的MeltsViewModel(聚合器、记录器、服务、configManagerFactory);//所有这些都是模拟对象
vm.refreshMels();
线程睡眠(毫秒延迟ForEventPublish*100);
mocky.VerifyAllExpectationsHaveBeenMet();
AreEqual(vm.meltsavable.Count,2);
Assert.AreEqual(vm.MeltsAvailable[0].MeltIdentifier,“TST0001”);
Assert.AreEqual(vm.MeltsAvailable[1].MeltIdentifier,“TST0002”);
}
测试在第一个Assert.AreEqual上始终失败。此时vm.MeltsAvailable为空

如果我去掉所有的螺纹并保持如下状态:

    public void RefreshMelts()
    {
        MeltsAvailable.Clear();
        IList<MeltDto> meltDtos = meltingAppService.GetActiveMelts();
        foreach (MeltDto availableMelt in meltDtos)
        {
            MeltsAvailable.Add(availableMelt);
        }
        OnPropertyChanged("MeltsAvailable");
    }
public void refreshMels()
{
meltsavable.Clear();
IList meltDtos=meltingAppService.getActiveMels();
foreach(熔接至可用熔接至熔接至)
{
熔化可用。添加(可用熔化);
}
不动产变更(“MELTSAVALIABLE”);
}
考试通过了

所以,很明显,线程有一些不喜欢的地方——但即使打开Debug->Exceptions->CLR Exceptions->shown,并且只关闭我的代码,我在RefreshMels中也没有任何异常

最奇怪的是,我将MeltDto对象加载到MeltsAvailable集合中的Dispatcher.Invoke调用似乎从未被调用。我可以用断点覆盖整个部分,它们永远不会被击中。增加线程。在我的测试中,睡眠时间甚至高达10秒也不会改变任何事情

为什么??为什么那个部分没有执行,为什么我不能进入它或打破它,为什么我没有得到异常,为什么它在执行中工作良好,但在测试中却不工作

多谢各位,
Steve

调度程序是一个绑定到执行线程的消息循环。当主线程空闲时,它处理其队列中的项目。在单元测试中,这永远不会发生。线程正忙,然后在测试完成时退出

如果使用Visual Studio运行测试,可以打开代码覆盖率高亮显示,您将看到Dispatcher.Invoke()中的代码从未被调用(它将以红色显示)

DispatcherFrame可用于触发调度器处理排队消息。将以下帮助器类添加到单元测试项目中:

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

    private static object ExitFrame(object frame) 
    { 
        ((DispatcherFrame)frame).Continue = false; 
        return null; 
    } 
}
在测试结束时(在断言之前),调用DispatcherHelper.DoEvents()。这将触发Dispatcher处理未完成的事件,例如向视图模型的可观察集合添加项的事件。然后,可以检查视图模型的属性,以验证这些属性设置是否正确