Следуя TDD, я разрабатываю приложение для iPad, которое загружает некоторую информацию из Интернета и отображает ее в списке, позволяя пользователю фильтровать этот список с помощью панели поиска.
Я хочу проверить, что по мере того, как пользователь вводит текст в строку поиска, обновляется внутренняя переменная с текстом фильтра, обновляется отфильтрованный список элементов, и, наконец, табличное представление получает сообщение «reloadData».
Это мои тесты:
- (void)testSutChangesFilterTextWhenSearchBarTextChanges
{
// given
sut.filterText = @"previous text";
// when
[sut searchBar:nil textDidChange:@"new text"];
// then
assertThat(sut.filterText, is(equalTo(@"new text")));
}
- (void)testSutReloadsTableViewDataAfterChangeFilterTextFromSearchBar
{
// given
sut.tableView = mock([UITableView class]);
// when
[sut searchBar:nil textDidChange:@"new text"];
// then
[verify(sut.tableView) reloadData];
}
ПРИМЕЧАНИЕ. Изменение свойства "filterText" запускает фактический процесс фильтрации, который был протестирован в других тестах.
Это работает нормально, поскольку мой код делегата searchBar был написан следующим образом:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
self.filterText = searchText;
[self.tableView reloadData];
}
Проблема в том, что фильтрация этих данных становится тяжелым процессом, который прямо сейчас выполняется в основном потоке, поэтому в это время пользовательский интерфейс блокируется.
Поэтому я подумал сделать что-то вроде этого:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSArray *filteredData = [self filteredDataWithText:searchText];
dispatch_async(dispatch_get_main_queue(), ^{
self.filteredData = filteredData;
[self.tableView reloadData];
});
});
}
Так что процесс фильтрации происходит в другом потоке, и когда он завершится, таблице будет предложено перезагрузить свои данные.
Вопрос в том... как мне протестировать эти вещи внутри вызовов dispatch_async?
Есть ли какой-нибудь элегантный способ сделать это, кроме временных решений? (например, подождать некоторое время и ожидать, что эти задачи будут завершены, не очень детерминировано)
Или, может быть, я должен поместить свой код по-другому, чтобы сделать его более тестируемым?
Если вам нужно знать, я использую OCMockito и OCHamcrest, автор Джон Рид.
Заранее спасибо!!