Как мне написать модульный тест для метода Flutter, который позже завершится с будущим? - PullRequest
1 голос
/ 10 ноября 2019

Я пишу модульный тест для метода Flutter, который вызывает асинхронный метод, а затем возвращает его, оставляя асинхронное выполнение как и когда. Мой тест не проходит "после того, как он уже завершен".

Вот мой тест:

    test('mark as viewed', () {
      final a = Asset();
      expect(a.viewed, false);
      a.markAsViewed();
      expect(a.viewed, true);
    });

и вот метод, который он тестирует:

  void markAsViewed() {
    viewed = true;
    Repository.get().saveToStorage();
  }

saveToStorage()Метод асинхронный, который я просто оставляю для выполнения в фоновом режиме.

Как мне заставить эту работу работать? Провал теста говорит мне Make sure to use [expectAsync] or the [completes] matcher when testing async code., но я не вижу, как это сделать. Может кто-нибудь объяснить или указать мне правильную документацию, пожалуйста? Я не могу найти ничего о том, как обрабатывать эти асинхронные операции, когда возвращается не Future, а просто оставлено для завершения отдельно.

Чтобы было ясно - этот модульный тест не касается проверки того,он сохраняется в хранилище, просто базовый тест по установке viewed равным true.

Отредактировано

Ошибка следующая:

package:flutter/src/services/platform_channel.dart 319:7  MethodChannel.invokeMethod
===== asynchronous gap ===========================
dart:async                                                _asyncErrorWrapperHelper
package:exec_pointers/asset_details.dart                  Repository.saveToStorage
package:exec_pointers/asset_details.dart 64:22            Asset.markAsViewed
test/asset_details_test.dart 57:9                         main.<fn>.<fn>
This test failed after it had already completed. Make sure to use [expectAsync]
or the [completes] matcher when testing async code.

1 Ответ

0 голосов
/ 10 ноября 2019

Этот код тесно связан с проблемами реализации, которые затрудняют его изолированное тестирование.

Следует изменить его код, чтобы он соответствовал более твердому проекту с явными зависимостями, которые можно заменить при тестировании в изоляции (модульное тестирование)

Например

class Asset {
    Asset({Repository repository}) {
        this.repository = repository;
    }

    final Repository repository;
    bool viewed;

    void markAsViewed() {
        viewed = true;
        repository.saveToStorage();
    }

    //...
}

Таким образом, при тестировании макета / заглушки зависимости можно избежать нежелательного поведения.

// Create a Mock Repository using the Mock class provided by the Mockito package.
// Create new instances of this class in each test.
class MockRepository extends Mock implements Repository {}

main() {
  test('mark as viewed', () {
    final repo = MockRepository();
    // Use Mockito to do nothing when it calls the repository
    when(repo.saveToStorage())
      .thenAnswer((_) async => { });

    final subject = Asset(repo);
    expect(subject.viewed, false);
    subject.markAsViewed();
    expect(subject.viewed, true);
    //
    verify(repo.saveToStorage());
  });
}

Теперь тест долженуметь работать без зависимости от поведения зависимостей.

Ссылка Введение в модульное тестирование
Ссылка Ложные зависимости с использованием Mockito
Ссылка mockito 4.1.1

...