Поэтому я пишу модульные тесты для одной из моих моделей представления в мобильном приложении Xamarin. Метод, который я тестирую, выглядит так:
public async Task RefreshItems()
{
var departamentsObservable = _dataService.GetDepartaments();
departamentsObservable.ObserveOn(SynchronizationContext.Current).Subscribe(items =>
{
Departaments.ReplaceWithRange(items);
});
await departamentsObservable.FirstOrDefaultAsync();
}
Метод _dataService.GetDepartaments();
возвращает IObservable<IEnumerable<Departament>>
.
Я использую Observable
и Subscribe
вместо простого метода, который возвращает Task<IEnumerable<Departament>>
, потому что в моем случае Observable
"вернется" дважды (один раз с данными из кеша, а другой раз с недавно полученными данными из сети).
Для тестирования я, конечно, издеваюсь над методом _dataService.GetDepartaments();
следующим образом:
public IObservable<IEnumerable<Departament>> GetDepartaments()
{
return Observable.Return(MockData.Departaments);
}
Таким образом, метод немедленно возвращает фиктивные данные.
И мой тест для метода RefreshItems
выглядит так:
[Fact]
public async Task RefreshItemsTest()
{
await _viewModel.RefreshItems();
Assert.Equal(MockData.Departaments, _viewModel.Departaments,
new DepartamentComparer());
}
Проблема в том, что этот тест случайным образом терпит неудачу (примерно 1 из 10 раз). В основном коллекция Departaments
в модели представления, которая должна обновляться, когда Observable
"возвращает" пуста.
Я должен добавить, что я использую тестовую среду xUnit 2.1.0 и средство запуска консоли xUnit в Xamarin Studio.
EDIT: Предложение Enigmativity создает исключение Последовательность не содержит элементов только при запуске в средстве выполнения тестов. Ниже приведен минимальный пример кода для демонстрации проблемы:
using System;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Reactive.Linq;
using System.Threading;
using System.Collections.Generic;
namespace TestApp
{
public class TestViewModel
{
public ObservableCollection<TestDepartament> Departaments { get; set; }
private ITestDataService _dataService;
public TestViewModel(ITestDataService dataService)
{
_dataService = dataService;
Departaments = new ObservableCollection<TestDepartament>();
}
public async Task RefreshItems()
{
var facultiesObservable = _dataService.GetDepartaments();
await facultiesObservable.ObserveOn(SynchronizationContext.Current).Do(items =>
{
Departaments.Clear();
foreach(var item in items)
Departaments.Add(item);
});
}
}
public interface ITestDataService
{
IObservable<IEnumerable<TestDepartament>> GetDepartaments();
}
public class MockDataService : ITestDataService
{
public IObservable<IEnumerable<TestDepartament>> GetDepartaments()
{
return Observable.Return(TestMockData.Departaments);
}
}
public static class TestMockData
{
public static List<TestDepartament> Departaments
{
get
{
var departaments = new List<TestDepartament>();
for (int i = 0; i < 15; i++)
{
departaments.Add(new TestDepartament
{
Name = $"Departament {i}",
ImageUrl = $"departament_{i}_image_url",
ContentUrl = $"departament_{i}_content_url",
});
}
return departaments;
}
}
}
public class TestDepartament
{
public string ContentUrl { get; set; }
public string Name { get; set; }
public string ImageUrl { get; set; }
}
}
А это тест xUnit:
public class DepartamentsViewModelTests
{
private readonly TestViewModel _viewModel;
public DepartamentsViewModelTests()
{
var dataService = new MockDataService();
_viewModel = new TestViewModel(dataService);
}
[Fact]
public async Task RefreshItemsTest()
{
await _viewModel.RefreshItems();
Assert.Equal(TestMockData.Departaments, _viewModel.Departaments);
}
}
DepartmentComparer
неисправен? - person myermian   schedule 15.10.2016