Как выполнить модульное тестирование ViewModel с помощью асинхронного метода.
Я не уверен, с чего начать, но позвольте мне дать вам краткое представление о том, где я нахожусь и чего я хочу достичь. Я новичок в модульном тестировании на MVVM и испытываю трудности при тестировании команд, которые я раскрыл, используя свойства команд делегата PRISM. Мои команды делегатов вызывают асинхронный метод, который нужно ждать, чтобы я мог получить реальный результат. Ниже приведен асинхронный метод, который вызывается методом, который я хотел проверить.
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.
1 ответ
Ваш метод GetTasksAsync должен возвращать задачу, чтобы вы могли ее подождать.
Я рекомендую эту серию на 9 канале, особенно этот эпизод, объясняющий вашу проблему.
Просто чтобы было понятно: просто измените подпись GetTasksAsync на
Task GetTasksAsync();
позволяет вам сделать это:
var t = GetAsync();
t.Wait();
Assert(...);
Если вы действительно хотите проверить команду в своих модульных тестах, а не метод, вызываемый этой командой, вы можете использовать поле в вашей ViewModel для хранения ожидающей (не очень чистой) задачи или заменить свой DelegateCommand чем-то вроде описанного в этот пост: Awaitable DelegateCommand
Обновление: в дополнение к сообщению в блоге и с учетом того, что вы используете PRISM, вам следует взглянуть на Project Kona из той же команды, что и PRISM. Они фактически реализовали DelegateCommand для поддержки AsyncHandlers