Flutter测试中如何用Fake timer验证getAccessToken轮询逻辑
Dart官方生态提供了完整的假时间模拟能力,不需要真实等待即可完成测试,实现步骤如下:
实现方案
1. 依赖准备
你需要添加两个开发依赖到pubspec.yaml的dev_dependencies节点:
clock:官方提供的时间抽象层,用来替换硬编码的DateTime.now(),方便测试时注入假时间fake_async:官方提供的假时间调度工具,可以模拟时间流逝、快进所有异步延迟,不需要真实等待
2. 生产代码改造
你现有代码里的时间判断用了硬编码的DateTime.now(),需要替换为clock包提供的可注入时间:
// 先导入clock包 import 'package:clock/clock.dart'; // 把原来的时间判断行 // final isExpired = DateTime.now().isAfter(created.add(expiresIn)); // 替换为 final isExpired = clock.now().isAfter(created.add(expiresIn));
3. 完整测试代码实现
用fake_async包裹测试逻辑,模拟时间流逝,同时用mock框架的verify方法验证调用次数即可:
import 'package:fake_async/fake_async.dart'; import 'package:clock/clock.dart'; test('getAccessToken polling', () { fakeAsync((async) { // 初始化MockClient final client = MockClient(); when(client.post(any, headers: anyNamed('headers'))).thenAnswer( (_) async => Response('{"error": "authorization_pending"}', 400), ); final authDataProvider = AuthenticationDataprovider( 'clientId', 'clientSecret', 'host', client, ); // 记录方法抛出的异常 Object? thrownError; // 注入固定初始时间调用方法,不需要await,fakeAsync会控制异步调度 final future = withClock( Clock(() => DateTime(2024, 1, 1, 0, 0, 0)), () => authDataProvider.getAccessToken( 'test_code', DateTime(2024, 1, 1, 0, 0, 0), const Duration(seconds: 60), const Duration(seconds: 5), ), ); future.catchError((e) => thrownError = e); // 第一次调用立即执行,验证首次调用 verify(client.post(any, headers: anyNamed('headers'))).called(1); expect(thrownError, isNull); // 每次快进5秒,验证调用次数 for (int i = 1; i <= 9; i++) { async.elapse(const Duration(seconds: 5)); verify(client.post(any, headers: anyNamed('headers'))).called(i + 1); expect(thrownError, isNull); } // 最后快进到超过60秒有效期 async.elapse(const Duration(seconds: 15)); // 验证最终抛出预期异常 expect(thrownError, isA<GetAccessTokenPollingException>()); // 验证累计调用次数符合预期 verify(client.post(any, headers: anyNamed('headers'))).called(10); verifyNoMoreInteractions(client); }); });
核心说明
fake_async会接管所有的Future.delayed调度,你调用elapse方法快进时间的时候,所有到期的延迟任务会立即执行,不需要真实等待时间,整个测试运行只需要几毫秒- 用
clock包替换硬编码的DateTime.now()是必须的,否则你的过期时间判断用的还是系统真实时间,假时间不会生效 - 你可以根据自己的实际业务逻辑调整循环次数和快进时长,验证调用次数直接用mock框架的
verify方法即可
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

