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

Flutter单元测试:如何验证fetchNotification中isProcess的状态变化?

如何测试NotificationProvider中isProcess的完整状态变化

问题描述

我希望测试isProcess属性是否会先变为true再变为false,但目前仅能测试fetchNotification方法执行完成后isProcess为false。请问该如何测试isProcess的完整状态变化?

NotificationProvider相关代码

/// A flag that indicates whether the NotificationProvider is being processed.
bool _isProcess = false;

set isProcess(bool value) {
  _isProcess = value;
  notifyListeners();
}

bool get isProcess => _isProcess;

NotificationProvider({required this.fetchNotificationUseCase});

//TODO("Satoshi"): catch exception or error
/// Fetch notification from api-server.
Future<void> fetchNotification() async {
  try {
    isProcess = true;
    final res = await fetchNotificationUseCase.fetchNotification();

    notificationList.clear();
    notificationList.addAll(res);

    isProcess = false;
    notifyListeners();
  } catch (e) {
    isProcess = false;
    notifyListeners();
    debugPrint(e.toString());
  }
}

现有测试代码

test('then isProcess is being false', () async {
  await notificationProvider.fetchNotification();

  expect(notificationProvider.isProcess, false);
});

解决方案

要验证isProcess先true后false的完整状态变化,核心是不立即await异步方法,而是在异步执行过程中捕获中间状态,或通过监听记录状态变更时序。以下是两种实用方案:

方案1:监听状态变更记录完整时序

利用Provider的addListener方法,记录每次isProcess的变化值,最后验证状态流转是否符合预期:

test('isProcess should transition from true to false', () async {
  final statusHistory = <bool>[];
  // 添加监听器,每次状态变更时记录当前isProcess值
  notificationProvider.addListener(() {
    statusHistory.add(notificationProvider.isProcess);
  });

  // 启动异步方法但不立即await
  final fetchTask = notificationProvider.fetchNotification();

  // 此时异步方法已进入执行阶段,isProcess应为true
  expect(notificationProvider.isProcess, true);

  // 等待异步方法执行完成
  await fetchTask;

  // 验证状态变化的顺序:先变为true,再回到false
  expect(statusHistory, [true, false]);
  // 最终状态验证
  expect(notificationProvider.isProcess, false);
});

方案2:Mock UseCase添加延迟确保可捕获中间状态

如果fetchNotificationUseCase的执行速度过快,中间状态可能一闪而过导致测试无法捕获,可以给mock的UseCase添加延迟:

// 先实现带延迟的Mock UseCase
class MockFetchNotificationUseCase extends Mock implements FetchNotificationUseCase {
  @override
  Future<List<Notification>> fetchNotification() async {
    // 模拟网络请求延迟,给测试留足检查中间状态的时间
    await Future.delayed(const Duration(milliseconds: 50));
    return [];
  }
}

// 测试代码
test('isProcess changes to true during fetch then back to false', () async {
  final mockUseCase = MockFetchNotificationUseCase();
  final provider = NotificationProvider(fetchNotificationUseCase: mockUseCase);

  // 启动异步任务
  final fetchFuture = provider.fetchNotification();

  // 立即检查中间状态
  expect(provider.isProcess, true);

  // 等待任务完成后检查最终状态
  await fetchFuture;
  expect(provider.isProcess, false);
});

关键注意点

  • 不要直接await fetchNotification()后再检查,这样会跳过中间的true状态,因为await会等待整个异步方法执行完毕。
  • 监听方案适合需要严格验证状态流转顺序的场景,mock延迟方案更简洁,适合只需要确认中间状态存在的场景。

内容的提问来源于stack exchange,提问作者임세준

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 17:15:08