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

Flutter测试:如何在首次setState后校验加载组件

Flutter Widget测试:验证异步操作中的加载状态

问题根源

你的按钮点击触发的异步方法中,若API调用是立即完成的(比如无延迟的Mock实现),两次setState会在同一帧周期内执行。调用普通的pump()会等待所有微任务完成,导致UI直接跳转到loading=false的状态,自然无法捕获到加载组件的显示状态。

解决方法

通过控制异步流程的时机,让第一次setState后的UI状态被单独捕获,具体有两种常用方案:


方案1:给Mock API添加延迟,配合pump(Duration.zero)校验

先修改Mock API,模拟真实API的延迟响应:

class MockApi extends Mock implements Api {
  @override
  Future<void> targetApiMethod() async {
    // 模拟API调用的延迟时长
    await Future.delayed(const Duration(milliseconds: 100));
  }
}

再调整测试代码,精准控制UI刷新时机:

testWidgets("验证点击按钮后显示加载组件", (widgetTester) async {
  final Api api = MockApi();
  await widgetTester.pumpWidget(MyWidget(api: api));

  // 触发按钮点击
  await widgetTester.tap(find.byType(TextButton));
  // 强制刷新当前帧,此时第一次setState已执行,API仍在"请求中"
  await widgetTester.pump(Duration.zero);

  // 校验加载组件是否显示
  expect(find.byType(Loading), findsOneWidget);

  // 可选:继续测试加载完成后的状态
  await widgetTester.pumpAndSettle();
  expect(find.byType(Loading), findsNothing);
});

方案2:用Completer手动控制API完成时机(更灵活)

通过Completer完全掌控异步流程的节点,适合复杂场景测试:

testWidgets("验证加载状态(手动控制API流程)", (widgetTester) async {
  final Completer<void> apiCompleter = Completer();
  final Api api = MockApi();
  
  // 让Mock API返回Completer的Future
  when(api.targetApiMethod()).thenAnswer((_) => apiCompleter.future);

  await widgetTester.pumpWidget(MyWidget(api: api));

  await widgetTester.tap(find.byType(TextButton));
  await widgetTester.pump(Duration.zero);

  // 此时API未完成,加载组件处于显示状态
  expect(find.byType(Loading), findsOneWidget);

  // 手动触发API完成
  apiCompleter.complete();
  await widgetTester.pumpAndSettle();

  // 校验加载组件是否消失
  expect(find.byType(Loading), findsNothing);
});

关键说明

  • pump(Duration.zero):强制Flutter刷新当前帧,仅执行已调度的setState,不会等待后续异步任务完成,刚好能捕获第一次setState后的加载状态。
  • 普通pump():会等待所有微任务执行完毕,若API无延迟,两次setState会被一次性执行,导致加载状态被跳过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 19:38:22