フラッタにモッカトを使う


助けてくれたなら、

簡単に説明します.
  • セットアップ
  • Mocktoを使っている倉庫をモッキングすること
  • リポジトリの書き込み単位テスト
  • ビューモデルの書き込み単位テスト
  • (オプション)コードカバレッジ
  • セットアップ


    単位テストが生のWebサービスまたはデータベースからデータを取得するクラスに依存する場合がしばしばあります.これはいくつかの理由で不便です.
  • ライブサービスやデータベースを呼び出すと、実行をスローダウンします.
  • Live Webサービスまたはデータベースを使用して、すべての可能な成功と失敗のシナリオをテストすることは困難です.
  • モッカート
    クラスの別の実装を作成することによって、mock依存関係を作成できます.を利用してMockito package ショートカットとして.
    以下はモッカトの背後にある一般的な考え方です

    Rather than relying on a live web service or database, you can “mock” these dependencies. Mocks allow emulating a live web service or database and return specific results depending on the situation.


    我々はmockito 単位テストを書くためのパッケージとbuild_runner . プラグインをあなたのpubspec.yaml ファイル
    # pubspec.yaml
    dependencies:
      mockito: ^5.1.0
    dev_dependencies:
      build_runner: ^2.1.7
    

    Detailed description here.


    を使用したリポジトリ


    これを始める前に、我々が我々のアプリのために使用したアーキテクチャを見ましょう
    アーキテクチャで使用されるアーキテクチャ
    スクリーンごとに、次のようになります.

  • Repository : ビジネスロジックを扱う

  • ViewModel : UIとリポジトリの間のブリッジ

  • View : ユーザに見える実際の画面

  • Model : 応答はモデルにキャストされ、ビューで消費される.
  • を用いたリポジトリテスト

  • これが我々のhome repository のようです.
  • abstract class HomeRepo {
      Future<CarouselModel> fetchData();
    }
    class HomeRepoImpl extends HomeRepo {
      @override
      Future<CarouselModel> fetchData() async {
        await Future.delayed(const Duration(milliseconds: 1800));
        final resp = await  rootBundle.loadString('assets/data/first_screen.json');
        return carouselModelFromJson(resp);
      }
    }
    
    上記のスニペットでは、ネットワーク遅延をシミュレートするために手動遅延を作成しています.
  • 我々の倉庫を嘲笑するために、我々は最初にファイルをつくりますhome_repo_test.dart 下の下のテストフォルダーの下に
  • RACK MOCKITOを用いたリポジトリテスト

    Note: The tests should follow test/folder_name/<name>_test.dart pattern

  • ファイルの中で、注釈を追加します@GenerateMocks([HomeRepoTest]) を生成するMockHomeRepoTest クラスウィズmockito .
  • By annotating a library element (such as a test file’s main function, or a class) with @GenerateMocks, you are directing Mockito's code generation to write a mock class for each "real" class listed, in a new library.


    // IMPORTS OMITTED FOR BREVITY
    class HomeRepoTest extends Mock implements HomeRepo {}
    @GenerateMocks([HomeRepoTest])
    Future<void> main() async {
    }
    
    HomeRemoteTest :生成されたクラスで参照される模擬クラス
    mockhomerepotest :内部の関数を実装する模擬クラスHomeRepo次に、次のコマンドを実行しているmockを生成します.
    flutter pub run build_runner build
    
    生成されたmocksに位置しますhome_repo_test.mocks.dart . テストファイル内でこのファイルをインポートします.
  • 上記のすべての手順が正しく行われたならば、我々はこのようなものを見るべきです
  • 模擬クラス

    リポジトリの書き込み単位テスト


    前のステップで行われたすべての必要なセットアップで、現在倉庫のために単位テストを書きましょう.
  • 我々は、内部の我々の模擬倉庫を初期化しますsetUpAll
  • Future<void> main() async {  
      late MockHomeRepoTest homeRepo;
      setUpAll(() {
        homeRepo = MockHomeRepoTest();
      });
      test('test fetchData', () async {
        final model = CarouselModel();
        when(homeRepo.fetchData()).thenAnswer((_) async {
          return model;
        });
        final res = await homeRepo.fetchData();
        expect(res, isA<CarouselModel>());
        expect(res, model);
      });
      test('test fetchData throws Exception', () {
        when(homeRepo.fetchData()).thenAnswer((_) async {
         throw Exception();
        });
        final res = homeRepo.fetchData();
        expect(res, throwsException);
      });
    }
    
  • 私たちは、倉庫の中で2つのテストをします:最初のもののためにwhen , thenAnswer APIは、スタブ機構を提供します.いったんスタブすると、メソッドは常に呼び出される回数にかかわらずスタブ値を返します.
  • when: Creates a stub method response. Mockito will store the fake call and pair the exact arguments given with the response. The response generators from Mockito includethenReturn, thenAnswer, and thenThrow.


    thenAnswer: Stores a function which is called when this method stub is called. The function will be called, and the return value will be returned.


    私たちはCarouselModel スタブから、それを主張する期待を使用するactual マッチmatcher .
    私たちのケースでは、私たちはそれがタイプ1であると予想しますCarouselModel 使用isA
  • 番目のテストでは、スタブから例外をスローします.我々は期待するactual マッチthrowsException 例外をスローする関数のmatcherです.
  • ビューモデルに対するライトユニットテスト


    我々は最初に我々の模擬ホームリポジトリとビューモデルを内部で初期化しますsetUpAll我々は、模擬倉庫にパスしますMockHomeRepoTest 我々のビューモデルには、リポジトリを必要なパラメータとして期待します.
    Future<void> main() async {
      late MockHomeRepoTest homeRepo;
      late HomeViewModel viewModel;
      setUpAll(() {
        homeRepo = MockHomeRepoTest();
        viewModel = HomeViewModel(repo: homeRepo);
      });
      test('test fetchData', () async {
        final model = CarouselModel();
       when(homeRepo.fetchData()).thenAnswer((_) async {
         return model;
       });
       await viewModel.fetchData();
       expect(viewModel.homeModel, model);
      });
    }
    
  • 上記のテストではwhen , thenAnswer 原研
  • 私たちはhomeRepo.fetchData() 使用when を返します.CarouselModel次に、実際の関数fetchData() ビューモデルの中からviewModel.fetchData()最後に、私たちはそれがタイプCarouselModel Matcherでは、リポジトリからモデルへの応答を設定しています.
    // HomeViewModel
    Future<void> fetchData() async {
      isLoading = true;
      _homeModel = await repo.fetchData();
      isLoading = false;
      notifyListeners();
    }
    

    コードカバレッジ


    Android Studioを使用している場合は、単にテストを右クリックして
    を使用してコードカバレッジ
    vscodeの場合は、次の拡張モジュールをインストールします
  • Flutter Coverage
  • Coverage Gutters
  • 次のコマンドを実行します
    flutter test --coverage
    
    これはlcov.info これにはカバレッジ情報が含まれます.
    コードカバレッジ
    さて、VSCodeの左側のテストアイコンをクリックし、コードカバレッジを見ることができます.良い記事here
    ビューモデルのコードカバレッジ
    Source code.
    助けてくれたなら、