Как протестировать асинхронные функции, которые обновляют объект PublishSubject или BehaviorSubject (RxDart) во Flutter - PullRequest
0 голосов
/ 31 мая 2019

Я изучал флаттер в течение нескольких недель и пришел из Android, поэтому мне это нравится, и я также был рад узнать, что Flutter был разработан с учетом тестирования с самого первого дня.Однако у меня возникла проблема при запуске следующего теста.

main() => {
  test('test get popular repos', () async {
    final testOwner = Owner(1010, "testLink");
    final testRepo =
        Repo(101, testOwner, "testRepo", "description", 'htmlUrl', 500);
    final testRepoResponse = RepoResponse(List.from([testRepo]), null);
    final uiModel = PopRepo(testRepo.owner.avatarUrl, testRepo.name,
        testRepo.description, "Stars: ${testRepo.stargazersCount}");
    final searchData = SearchData(List.from([uiModel]), null);

    final Repository mockRepository = _mockRepository();

    when(mockRepository.getPopularReposForOrg("org"))
        .thenAnswer((_) => Future.value(testRepoResponse));

    final repoSearchBloc = RepoSearchPageBloc(mockRepository);
    await repoSearchBloc.getPopularRepos("org");


    await expectLater(repoSearchBloc.resultSubject.stream, emits(searchData));
  }),
};

class _mockRepository extends Mock implements Repository {}

Мой RepoSearchBloc берет данные из репозитория и преобразует их в модель пользовательского интерфейса.Наконец, он отправляет данные, готовые к пользовательскому интерфейсу, субъекту

. Это тестируемый метод в RepoSearchBloc

getPopularRepos(String org) async {
if (org == null || org.isEmpty)
  return resultSubject.add(SearchData(List(), null));
RepoResponse response = await _repository.getPopularReposForOrg(org);
if (response.error == null) {
  List<Repo> repoList = response.results;
  repoList.sort((a, b) => a.stargazersCount.compareTo(b.stargazersCount));
  var uiRepoList = repoList
      .map((repo) => PopRepo(repo.owner.avatarUrl, repo.name,
          repo.description, "Stars: ${repo.stargazersCount}"))
      .take(3)
      .toList();
  resultSubject.add(SearchData(uiRepoList, null));
} else {
  ErrorState error = ErrorState(response.error);
  resultSubject.add(SearchData(List(), error));
}

. Когда я запускаю тест, я продолжаю получать это сообщение, независимо от того, что якажется ли это с BehaviorSubject или PublishSubject:

ERROR: Expected: should emit an event that <Instance of 'SearchData'>
  Actual: <Instance of 'BehaviorSubject<SearchData>'>
   Which: emitted * Instance of 'SearchData'

Есть идеи, как пройти этот тест?

1 Ответ

0 голосов
/ 31 мая 2019

Закончилось выяснение этого с помощью пользователя Nico @Rodsevich из сообщества Flutter Glitter

в любом случае, используя его предложение использовать await for

Я пришел к следующему решению, которое прошло

    await for (var emittedResult in repoSearchBloc.resultSubject.stream) {
      expect(emittedResult.results[0].repoName, testRepo.name);
      return;
    }

В библиотеке RxDart есть несколько предметных тестов для справки , но моя тема, размещаемая в асинхронном режиме, не соответствовала их тестам, поэтому это решение оказалось именно тем, что мне было нужно.

Кроме того, комментарий @ Abion47 также, кажется, делает свою работу, когда я перемещаю асинхронный внутри параметра для ожидаемого

expectLater( (await repoSearchBloc.resultSubject.stream.first as SearchData).results[0].repoName, testRepo.name);
...