Рассмотрим следующую весьма упрощенную модель представления для выборки и показывает список проектов:Можно ли исключить ошибки тестирования модулей в командах, обертывающих асинхронную лямбда?
public class ProjectListViewModel
{
private readonly IWebService _webService;
public ICommand RefreshCommand { get; }
// INotifyPropertyChanged implementation skipped for brevity
public ObservableCollection<Project> Projects { get; set; }
public ProjectListViewModel(IWebService serverApi)
{
_serverApi = serverApi;
// ICommand implemented by Xamarin.Forms
RefreshCommand = new Command(async() => await RefreshAsync());
}
private async Task RefreshAsync()
{
try
{
Projects = await _webService.GetProjectsAsync();
}
catch (TaskCanceledException)
{
// Empty (task only cancelled when we are navigating away from page)
}
}
}
Используя NUnit и Moq, я пытаюсь тест, когда GetProjectsAsync
бросает TaskCanceledException
, то ViewModel будет поймать его. Ближайший я получаю это:
[Test]
public void When_Refreshing_Catches_TaskCanceledException()
{
// Arrange
webService = new Mock<IServerApi>();
webService.Setup(mock => mock.GetProjectsAsync())
.ThrowsAsync(new TaskCanceledException());
vm = new ProjectListViewModel(webService.Object);
// Act and assert
Assert.That(() => vm.RefreshCommand.Execute(null), Throws.Nothing);
}
тест проходит, но, к сожалению, это ошибочный - это все еще проходит, если я брошу, например, Исключение вместо TaskCanceledException. Насколько я знаю, причина в том, что исключение не пробивается мимо команды lambda, async() => await RefreshAsync()
, поэтому исключение, генерируемое GetProjectsAsync, никогда не будет обнаружено в результате теста. (При выполнении фактического приложение однако, TaskCanceledException будет пузыриться и разбить приложение, если не поймали. Я подозреваю, что это связано с контексты синхронизации, из которых у меня есть очень ограниченное понимание.)
Это работает, если я отладки тест - если я высмеиваю это, чтобы бросить Exception, он сломается на линии с помощью определения команды/лямбда, и если я выкину это TaskCanceledException, тест пройдет.
Обратите внимание, что результаты те же, если я использую Throws вместо ThrowsAsync. И в случае, если это имеет значение, я использую тестовый бегун в ReSharper 2016.2.
Использование nUnit, возможно ли вообще исключить исключения для тестирования при выполнении команд «async»? Возможно ли это без написания пользовательской реализации команды?
Вы посмотрели на это? http://stackoverflow.com/a/15636814/4625433 –