如何修正Stream监听器内异步函数调用的单元测试验证时机问题?
解决Stream异步回调的单元测试验证问题
问题核心是Stream监听器内的updateToken是异步操作,而verify在该异步操作完成前就执行了,导致验证失败。以下是两种可靠的解决方法:
方法一:使用Completer跟踪异步操作完成
通过给mock的updateToken方法绑定一个Completer,等待其完成后再执行验证,能精准确保异步逻辑执行完毕:
test('should update notification token when refreshed', () async { const fakePushToken = 'token'; final fakeStream = StreamController<String>(); final completer = Completer<void>(); // 模拟Stream when(() => liveActivityRepo.activityUpdateStream) .thenAnswer((_) => fakeStream.stream); // 模拟updateToken,调用时完成Completer when(() => userRepo.updateLiveActivityToken(token: fakePushToken)) .thenAnswer((_) async { completer.complete(); }); useCase.run(); fakeStream.add(fakePushToken); // 发射事件 await completer.future; // 等待异步操作完成 verify(() => userRepo.updateLiveActivityToken(token: fakePushToken)).called(1); });
方法二:等待微任务队列清空
由于Stream的异步回调会被加入微任务队列,通过await Future.microtask(() {})可以让当前测试暂停,直到所有微任务执行完毕:
test('should update notification token when refreshed', () async { const fakePushToken = 'token'; final fakeStream = StreamController<String>(); when(() => liveActivityRepo.activityUpdateStream) .thenAnswer((_) => fakeStream.stream); useCase.run(); fakeStream.add(fakePushToken); // 等待微任务队列执行完,确保异步回调完成 await Future.microtask(() {}); verify(() => userRepo.updateLiveActivityToken(token: fakePushToken)).called(1); });
注意事项
原测试代码中存在笔误:fakeStream.add(fakeUpdate)里的fakeUpdate应改为fakePushToken,否则会导致参数不匹配,即使异步逻辑执行了,verify也会失败。
内容的提问来源于stack exchange,提问作者GGirotto
相关产品推荐
相关产品推荐

