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

Flutter中如何用Mockito正确模拟并验证返回Future的函数?

问题:模拟返回Future的函数时出现类型错误

我尝试模拟一个返回Future<bool>且接收String类型参数的函数,编写了如下测试代码:

final Future<bool> Function(String) _handleFilterSelect = MockFunction();

when(_handleFilterSelect.call('/view/movie_1234'))
    .thenAnswer((_) => Future.value(true));
FilterList filterList = new FilterList(
  '/view/movie',
  onFilterSelect: _handleFilterSelect,
);
await widgetTester.pumpWidget(MaterialApp(
  localizationsDelegates: delegate,
  home: Scaffold(
    body: filterList,
  ),
  theme: ThemeUtil().getCurrentTheme()!.defaultThemeData,
));
await widgetTester.pumpAndSettle();
final filtersFinder = find.byType(ListTile);
await widgetTester.tap(filtersFinder);
await widgetTester.pumpAndSettle();
verify(_handleFilterSelect('/view/movie_1234')).called(1);

// 测试外部的代码
class MockFunction extends Mock {
  Future<bool> call(String param);
}

运行测试时抛出如下错误:

The following _TypeError was thrown running a test: type 'Null' is not a subtype of type 'Future'

当该函数为非Future返回类型时测试可正常运行,请问正确实现返回Future类型的_handleFilterSelect的方式是什么?


解决方案

这个错误的核心原因是:Mock类默认会返回null,当你的Stub(即when语句)没有匹配到实际调用时,就会返回null,而组件期望的是Future<bool>类型,因此触发类型转换错误。结合你的场景,有两种可靠的修复方式:

方式一:修正Stub的匹配方式

Dart中调用函数func(param)等价于func.call(param),但Mockito对这两种写法的匹配逻辑可能存在差异。直接Stub函数调用而非call方法,能确保匹配更准确:

// 替换原有的when语句
when(_handleFilterSelect('/view/movie_1234'))
    .thenAnswer((_) => Future.value(true));

同时保持MockFunction的定义不变即可。

方式二:使用typedef定义函数类型,让Mock类实现该类型

通过typedef明确函数签名,能让Mockito更好地识别函数类型,避免匹配问题:

  1. 先定义函数类型的typedef:
typedef FilterSelectCallback = Future<bool> Function(String);
  1. 修改Mock类实现该typedef:
class MockFilterSelectCallback extends Mock implements FilterSelectCallback {}
  1. 在测试中使用这个Mock类:
final _handleFilterSelect = MockFilterSelectCallback();

// Stub函数调用
when(_handleFilterSelect('/view/movie_1234'))
    .thenAnswer((_) => Future.value(true));

// 后续的组件初始化、测试逻辑保持不变
FilterList filterList = FilterList(
  '/view/movie',
  onFilterSelect: _handleFilterSelect,
);
// ... 其余测试代码

额外注意事项

  • 确保组件调用onFilterSelect时传入的参数和你Stub的参数完全一致(比如路径是否带后缀、大小写是否匹配),否则Stub无法触发,依然会返回null。
  • 调用verify时,同样使用_handleFilterSelect('/view/movie_1234')而非call方法,保持和Stub的写法一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 18:52:37