【第十天 - Flutter Bloc Unit Test+Mocktail 范例】

前言

今日的程序码 => GITHUB
接续上一篇 【第九天 - Flutter Bloc+Cubit 架构教学】
今天要来介绍单元测试,如何和 bloc pattern 结合,如何使用 mocktail 产生假资料。

设定 YAML 档案

dependencies:
  mocktail: ^0.1.4
dev_dependencies:
  bloc_test: ^8.1.0

post_bloc_test

MockRepoImp,这边是我们示范如何写假的资料,但是我自己不喜欢这样写,因为这样写会需要写很多很多的 Code,因此後面我们有介绍另外一种写法,使用了强大的 mocktail套件,可以帮助我们解决这个问题。
Test

void main() {
 group('这个群组的测试名称', () {
   test('测试名称', () async{
     
   });
 });
}
// 架构 样子
Main
----|Group
----|-----|Test
----|-----|Test
----|-----|Test

Bloc_Test 官方文件

  • 一样释放 blocTest<Bloc,Test>
  • build 则是我们要去实作 new Bloc
  • act 事件
  • seed 设定当下状态,比方说我们触发这个状态的时候,当下状态是哪一个。
  • wait 模拟 delay 时间
  • skip 是一个可选的int,可用於跳过任意数量的状态。skip默认为 0。
  • verify 是用来检查程序码是否有触发 function 并且呼叫了几次
  • errors 用来检查 exception
  • expect 预计执行的 state
  • tearDown是可选的,可用於在测试运行後执行任何代码。tearDown应该用於在特定测试用例之後进行清理。

verify = 里面会有现在 state 的状态,然後我们就可以拿到 state 里面的参数来做验证了。
expect = 前面释放程序码结果,後面释放预计结果。
isA<>() = <> 里面就释放类别。

class MockRepoImp extends IPostRepository {
  @override
  Future<List<PostModel>> fetchData() async => [
        PostModel(
            userId: 1, id: 1, title: 'Mickey title', body: 'this is the body'),
        PostModel(
            userId: 2, id: 2, title: 'Ruby title', body: 'this is the body'),
      ];
}

void main() {
  group('Post Bloc Test', () {
    blocTest<PostBloc, IPostState>(
      '确认 FetchPostData 的状态是对的',
      build: () => PostBloc(repository: MockRepoImp()),
      act: (bloc) => bloc.add(FetchPostData()),
      // 设定事件的初始状态
      seed: () => PostLoading(),
      // 设定 Delay 时间
      wait: const Duration(milliseconds: 300),
      expect: () => [
        // isA<PostLoading>(), // 初始化的状态并不会被触发
        isA<PostSuccess>(),
      ],
    );

    blocTest<PostBloc, IPostState>(
      '预设 Sort by Id',
      build: () => PostBloc(repository: MockRepoImp()),
      act: (bloc) => bloc.add(FetchPostData()),
      verify: (bloc) {
        final _state = bloc.state as PostSuccess;
        expect(_state.postList.length, 2);
        expect(_state.postList[0].id, 1);
        expect(_state.postList[1].id, 2);
      },
    );
    //
    blocTest<PostBloc, IPostState>(
      'Sorted by title',
      build: () => PostBloc(repository: MockRepoImp()),
      act: (bloc) => bloc
        ..add(FetchPostData())
        ..add(SortPostEvent(sortState: SortState.title)),
      expect: () => [
        isA<PostSuccess>(),
        isA<PostSuccess>(),
      ],
      verify: (bloc) {
        final _state = bloc.state as PostSuccess;
        expect(_state.postList.length, 2);
        expect(_state.postList[0].id, 1);
        expect(_state.postList[1].id, 2);
      },
    );
  });
}

Mock 是什麽?

Mock 就是模拟行为,以下面的范例为例子,我们的 PostService 有一个 function 叫做 fetchData(),可是今天我单元测试,我想要能够控制 fetchData 回传的资料是什麽东西。因为这样才可以达到後面我去验证後面的结果。所以使用 Mock 可以让 fetchData 回传假的资料,回传任何型态的资料。有点类似覆写 fetchData 这个方法的感觉。

post_api_test

我们现在想要 Mock PostService 的话,我们就 extends Mock 然後 implements PostService 就可以了。

class MockPostService extends Mock implements PostService {}

这行是我们要覆写 fetchData() 然後希望他的假资料是 _mockList

when(() => _post_service.fetchData()).thenAnswer((_) async => _mockList);
class MockPostService extends Mock implements PostService {}

final _mockList = [
  PostModel(userId: 1, id: 1, title: 'Mickey title', body: 'this is the body'),
  PostModel(userId: 2, id: 2, title: 'Ruby title', body: 'this is the body'),
];

void main() {
  group('test_API', () {
    final _post_service = MockPostService();
    test('returns List<PostModel> and called only one time if the http call completes successfully', () async {
      //Arrange
      when(() => _post_service.fetchData()).thenAnswer((_) async => _mockList);
      // act
      final act = await _post_service.fetchData();
      // assert
      expect(act, isA<List<PostModel>>());
      verify(() => _post_service.fetchData()).called(1);
    });
  });
}

<<:  Rust-定义函式Function(一)

>>:  初学者跪着学JavaScript Day9 : 让我困惑的Literals

Day–3 Excel之快速移动栏列之术

欢迎大家,来到了第三天依旧充满干劲,今天要来跟大家介绍Excel的文字格式,以及今天的重点调整栏列的...

23. 闲聊 x VFS 办理英签申请

今天去 VFS 办理英签申请,纪录一下流程骗一天文章。 有後续应该也不会在这里更新 XD 流水帐 V...

30天打造品牌特色电商网站 Day.24 电商必用的各类提示

相信大家使用网站时,一定会遇到大大小小固有或弹出的提示框,这次的主题就是他! 提示框在用户经验上会以...

deep learning 能做什麽呢

今天是西雅图的周日,因为晚点要赶飞机去了所以决定今天介绍一些轻松有趣的deep learning应用...