Как дождаться асинхронной команды для юнит-тестирования? - PullRequest
0 голосов
/ 03 июня 2019

Я пытаюсь выполнить модульное тестирование команды, но поскольку она является асинхронной командой, метод теста переходит в утверждения до ее завершения. Я искал решения этой проблемы, и все они говорят о создании интерфейса AsyncCommand и т. Д., Что я не хочу делать, так как мне нужно только ждать команд для целей модульных тестов. Так есть ли другое решение, которое проще и не требует создания другого интерфейса и т. Д.

это мой командный класс:

   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 Ответ

4 голосов
/ 03 июня 2019

Так есть ли другое решение, которое является более простым и не требует создания другого интерфейса и т. Д.?

Нет и да.Есть другое решение.Это не проще.Самое простое и простое решение - использовать 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....
}

Опять же, я настоятельно рекомендую использовать IAsyncCommand.Реальная проблема заключается в том, что основные типы MVVM недостаточны.Поэтому большинство людей используют IAsyncCommand или MvxAsyncCommand или AsyncCommand или представляют логику команды как метод async Task на ВМ.

...