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,提问作者임세준
相关产品推荐
相关产品推荐

