如何等待异步命令进行单元测试?

时间:2019-06-03 10:30:16

标签: c# multithreading unit-testing async-await icommand

我正在尝试对命令进行单元测试,但是由于它是异步命令,因此测试方法会在命令完成之前进入断言。我已经找到了解决此问题的方法,他们都在谈论创建我不想做的AsyncCommand接口等,因为我只需要等待命令进行单元测试即可。那么是否有另一种解决方案,它更简单并且不需要创建其他接口等?

这是我的Command类:

   public class Command : ICommand
    {
        public void Execute(object parameter)
        {
          //exeute...
        }

        //other stuff....
    }

那是经过测试的课程:

pubic class MyClass
{
    private Command commandForTest;
    public Command CommandForTest
            {
                get
                {
                    if (commandForTest == null)
                    {
                        commandForTest = new Command(async (o) =>
                        {
                            if(someCondition)
                               await SomeMethod();
                             else
                               await AnotheMrthod();   

                        });
                    }
                    return commandForTest;
                }
            }
}

这是测试方法:

[TestMethod]
        public async Task Test()
{
    MyClass myclass = new MyClass();
    await Task.Run( () =>  myclass.CommandForTest.Execute());
    //Assert....
}

1 个答案:

答案 0 :(得分:4)

  

那么还有另一种解决方案,它更简单并且不需要创建其他接口等吗?

否,是的。还有另一种解决方案。 更简单。最简单,最直接的解决方案是使用IAsyncCommand interface。或一种AsyncCommand实现,您的单元测试可以将ICommand转换为(更易碎)。

但是,如果您想走艰难的路,那么可以,从技术上讲,您可以检测到async void方法何时完成。您可以通过编写自己的SynchronizationContext and listening to OperationStarted and OperationCompleted来实现。您还需要建立一个工作队列并编写一个处理该队列的主循环。

我有执行此操作的类型。它称为AsyncContext and it is part of AsyncEx。用法:

[TestMethod]
public void Test() // note: not async
{
  MyClass myclass = new MyClass();
  AsyncContext.Run(() =>
  {
    myclass.CommandForTest.Execute();
  });
  //Assert....
}

同样,我强烈建议您使用IAsyncCommand。真正的问题是核心MVVM类型不足。因此,大多数人在虚拟机上使用IAsyncCommandMvxAsyncCommandAsyncCommand或将命令逻辑作为async Task方法公开。