如何用async方法对ViewModel进行单元测试

本文关键字:单元测试 ViewModel 何用 async 方法 | 更新日期: 2023-09-27 18:05:46

我不知道从哪里开始,但让我给你一个简短的想法,我在哪里,我想实现什么。我对MVVM上的单元测试非常陌生,并且在使用PRISM委托命令属性测试我所暴露的命令时遇到了困难。我的委托命令调用async方法,它必须等待,这样我才能得到实际的结果。下面是我要测试的方法调用的一个async方法。

 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
                }
            }
        }

也是在我的VM中调用上面的async方法的命令

  this.GetTasksCommand = new DelegateCommand(this.GetTasks);
      void GetTasks()
        {
                GetTasksAsync();
        }
现在我的Test Method变成了
 [TestMethod]
        public void Command_Test_GetTasksCommand()
        {
          MyViewModel.GetTaskCommand.Execute(); // this should populate ViewModel.SimpleTask 
          Assert.IsTrue(MyBiewModel.SimpleTask != null)
        } 

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

如何用async方法对ViewModel进行单元测试

你的方法GetTasksAsync应该返回一个Task,这样你就可以等待它了

我推荐第九频道的这个系列节目,特别是这一集解释你的问题。

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

Task GetTasksAsync();

允许你这样做:

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

如果你真的想在单元测试中测试命令,而不是命令调用的实际方法,你可以在ViewModel中使用一个字段来存储等待的任务(不太干净),或者用这篇文章中描述的东西代替你的DelegateCommand:

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