You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测试带有droppable/restartable事件的Flutter Bloc?

解决Flutter Bloc中Droppable转换器的测试问题

要验证droppable()转换器的丢弃逻辑,核心是让第一个事件的处理处于异步耗时状态,这样后续事件进来时才会被转换器拦截丢弃。你的测试失败是因为事件处理是同步的,第一个事件处理完成后才会处理第二个,转换器没机会生效。

步骤1:修改事件处理函数为异步耗时

确保_mapSomeEvent包含异步延迟操作,模拟真实场景中的耗时任务:

class SomeBloc extends Bloc<SomeEvent, SomeState> {
  SomeBloc() : super(InitialState()) {
    on<SomeEvent>(
      _mapSomeEvent,
      transformer: droppable(),
    );
  }

  Future<void> _mapSomeEvent(SomeEvent event, Emitter<SomeState> emit) async {
    // 模拟异步耗时操作,让转换器有机会拦截后续事件
    await Future.delayed(const Duration(milliseconds: 50));
    
    if (event is DroppableEvent) {
      emit(StateFromDroppable());
    } else {
      emit(OtherStateFromSomeEvent());
    }
  }
}

步骤2:确保事件类型匹配

droppable()仅对同一事件类型生效,所以DroppableEvent必须是SomeEvent的子类:

abstract class SomeEvent extends Equatable {
  const SomeEvent();

  @override
  List<Object> get props => [];
}

class DroppableEvent extends SomeEvent {
  const DroppableEvent();
}

步骤3:调整测试代码

在act中同步连续添加两个事件,不需要await,确保第二个事件在第一个事件的异步处理过程中被提交:

blocTest<SomeBloc, SomeState>(
  'droppable转换器丢弃后续同类型事件,仅触发第一个事件的状态',
  build: () => SomeBloc(),
  act: (bloc) {
    bloc.add(DroppableEvent());
    // 立即添加第二个事件,此时第一个事件的处理还在进行中
    bloc.add(SomeEvent());
  },
  expect: () => [
    StateFromDroppable(),
  ],
);

这样测试就能符合预期:第一个DroppableEvent的异步处理未完成时,第二个SomeEvent被droppable()转换器丢弃,最终仅触发StateFromDroppable状态。

内容的提问来源于stack exchange,提问作者Ianmcuki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 14:55:21