5

我不知道从哪里开始,但让我简要介绍一下我在哪里以及我想要实现的目标。我对 MVVM 上的单元测试非常陌生,并且很难测试我使用 PRISM 委托命令属性公开的命令。我的委托命令调用必须等待的异步方法,以便我可以获得实际结果。下面是一个由我想测试的方法调用的 asyc 方法。

 async void GetTasksAsync()
        {
            this.SimpleTasks.Clear();
            Func<IList<ISimpleTask>> taskAction = () =>
                {
                    var result = this.dataService.GetTasks();
                    if (token.IsCancellationRequested)
                        return null;
                    return result;
                };
            IsBusyTreeView = true;

            Task<IList<ISimpleTask>> getTasksTask = Task<IList<ISimpleTask>>.Factory.StartNew(taskAction, token);
            var l = await getTasksTask;          // waits for getTasksTask


            if (l != null)
            {
                foreach (ISimpleTask t in l)
                {
                    this.SimpleTasks.Add(t); // adds to ViewModel.SimpleTask
                }
            }
        }

这也是我的虚拟机中调用上述异步方法的命令

  this.GetTasksCommand = new DelegateCommand(this.GetTasks);
      void GetTasks()
        {
                GetTasksAsync();
        }

现在我的测试方法就像

 [TestMethod]
        public void Command_Test_GetTasksCommand()
        {
          MyViewModel.GetTaskCommand.Execute(); // this should populate ViewModel.SimpleTask 
          Assert.IsTrue(MyBiewModel.SimpleTask != null)
        } 

目前我得到的是我的 ViewModel.SimpleTask = null 这是因为它不等待异步方法完成。我知道堆栈溢出中已经有一些相关的主题,但我找不到与我的 DelegateCommands 相关的内容。

4

1 回答 1

10

您的方法 GetTasksAsync 应该返回一个 Task 以便您可以真正等待它。

我在 Channel9 上推荐这个系列,特别是这一集来解释你的问题。

只是说清楚:只需将 GetTasksAsync 的签名更改为

Task GetTasksAsync();

允许您这样做:

var t = GetAsync();
t.Wait();
Assert(...);

如果您真的想在单元测试中测试命令而不是命令调用的实际方法,您可以使用 ViewModel 中的一个字段来存储要等待的任务(不是那么干净)或用类似中描述的内容替换您的 DelegateCommand这篇文章:Awaitable DelegateCommand

更新:除了博客文章,考虑到您正在使用 PRISM,您应该看看与 PRISM 来自同一团队的Project Kona 。他们实际上实现了 DelegateCommand 来支持 AsyncHandlers

于 2013-03-26T07:50:19.977 回答