简体   繁体   English

Flutter bloc:如何在 mocking 事件调用时测试 bloc 构造函数?

[英]Flutter bloc: how to test bloc constructor while mocking event calls?

I would like to test if a timer initialized by my constructor effectively calls a specific bloc event.我想测试由我的构造函数初始化的计时器是否有效地调用了特定的 bloc 事件。

import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';

class ExampleBloc extends Bloc<ExampleEvent, ExampleState> {
  ExampleBloc() : super(ExampleInitial()) {
    on<ExampleEvent>((event, emit) {});
    periodicTimer = Timer.periodic(Duration(minutes: 1), (timer) async {
      add(ExampleEvent());
    });
  }
  late Timer periodicTimer;

  @override
  Future<void> close() {
    periodicTimer.cancel();
    return super.close();
  }
}

@immutable
class ExampleEvent {}

@immutable
abstract class ExampleState {}

class ExampleInitial extends ExampleState {}

To test it, I thought about using a widget test because it would be possible to tester.pump() the duration from the timer.为了测试它,我考虑过使用小部件测试,因为可以tester.pump()来自计时器的持续时间。

import 'dart:async';

import 'package:bloc_test/bloc_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:indaband/example_bloc.dart';
import 'package:mocktail/mocktail.dart';

class ExampleBlocMock extends MockBloc<ExampleEvent, ExampleState>
    implements ExampleBloc {}

void registerFallbackValues() {
  registerFallbackValue<ExampleState>(ExampleInitial());
  registerFallbackValue<ExampleEvent>(ExampleEvent());
}

void main() {
  setUpAll(() {
    registerFallbackValues();
  });
  group(
    'Test',
    () {
      final bloc = ExampleBlocMock();
      final blocStateController = StreamController<ExampleState>.broadcast();
      when(() => bloc.stream).thenAnswer((_) => blocStateController.stream);

      testWidgets('test periodic timer', (WidgetTester tester) async {
        final bloc = ExampleBloc();
        final widget = BlocProvider(
          create: (context) => bloc,
          child: Container(),
        );
        await tester.pumpWidget(widget);
        await tester.pump(Duration(minutes: 1));
        verify(() => bloc.add(ExampleEvent())).called(1);
        await tester.pump(Duration(minutes: 1));
        verify(() => bloc.add(ExampleEvent())).called(2);
        await tester.pump(Duration(minutes: 1));
        verify(() => bloc.add(ExampleEvent())).called(3);
      });
    },
  );
}

I don't know if it's possible to mock only the .add(...) call, in order to make the timer available.我不知道是否可以只模拟.add(...)调用,以使计时器可用。

There's a few things wrong here:这里有一些问题:

  1. Your creating a mock bloc in your test, and it's not being used or verified at all given you're creating a 'real' bloc with the same name.您在测试中创建了一个模拟块,并且它根本没有被使用或验证,因为您正在创建一个具有相同名称的“真实”块。

  2. Your ExampleEvent isn't emitting a new state on each timer tick, so there's nothing to test or capture.您的ExampleEvent不会在每个计时器滴答声上发出新的 state,因此无需测试或捕获任何内容。

  3. Testing the bloc itself is a unit test, not a widget test.测试 bloc 本身是一个单元测试,而不是小部件测试。 The bloc_test package provides a convenient set of utilities to unit test blocs, read the docs. bloc_test package 提供了一组方便的实用程序来对块进行单元测试,请阅读文档。

  4. Bloc events/states must implement equality overrides to ensure a new state is emitted after each event, refer to the bloc docs and in-depth tutorials as to how the bloc package works. Bloc 事件/状态必须实现相等覆盖,以确保在每个事件之后发出新的 state,请参阅 bloc 文档和深入教程,了解 bloc package 如何工作。

Once the above is addressed, you can add test cases around verifying the emitted state is what you expect.解决上述问题后,您可以添加测试用例来验证发出的 state 是否符合您的期望。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM