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

an0*_*007 1 c# multithreading unit-testing icommand async-await

我正在尝试对命令进行单元测试,但是因为它是一个异步命令,所以在命令完成之前,测试方法会进入断言。我已经查找了这个问题的解决方案,他们都在谈论创建一个 AsyncCommand 接口等,我不想这样做,因为我只需要等待用于单元测试目的的命令。那么是否有另一种更简单的解决方案,不需要创建另一个界面等?

这是我的命令类:

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

        //other stuff....
    }
Run Code Online (Sandbox Code Playgroud)

那是测试类:

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;
                }
            }
}
Run Code Online (Sandbox Code Playgroud)

这是测试方法:

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

Ste*_*ary 6

那么是否有另一种更简单的解决方案,不需要创建另一个界面等?

不,是的。还有另一种解决方案。这并不简单。最简单和最直接的解决方案是使用IAsyncCommand接口。或者AsyncCommand您的单元测试可以将其转换ICommand为(更脆弱)的实现。

但是,如果您想走得更远,那么是的,您可以从技术上检测async void方法何时完成。您可以通过编写自己的内容SynchronizationContext并聆听OperationStarted和来OperationCompleted做到这一点。您还需要构建一个工作队列并编写一个处理该队列的主循环。

我有一个类型可以做到这一点。它被调用AsyncContext并且它是 的一部分AsyncEx。用法:

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

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