Flutter单元测试mocktail验证方法调用报非mock对象错误
错误原因
这个报错是三个问题共同导致的:
verify的回调写法错误:你写的() => repo.getResetPasswordToken只是获取了方法的引用(tear-off),没有传入参数实际调用该方法。mocktail的verify只能识别对mock对象方法的实际调用表达式,单纯拿方法引用不会被代理拦截,就会抛出Used on a non-mocktail object错误。- 测试逻辑缺失调用步骤:你在执行
verify之前,根本没有主动调用过一次getResetPasswordToken方法,就算verify写法正确,调用计数也是0,无法匹配called(1)的预期。 - 缺少方法返回值存根:mock对象的方法默认返回
null,但你的getResetPasswordToken返回值是非空的Future类型,如果不提前设置存根返回合法值,调用方法时会直接抛出类型错误。
修改方案
按照以下步骤调整测试代码即可:
- 在测试执行前初始化mock对象,并用
when给目标方法设置合法的测试返回值 - 在验证逻辑前,主动调用一次待测试的
getResetPasswordToken方法 - 修正
verify回调的写法,传入参数实际调用目标方法,不关心参数值时可以用any()做通配匹配
正确的测试代码示例:
import 'package:mocktail/mocktail.dart'; // 省略其他业务类导入 class RepoMock extends Mock implements Repository {} void main() { late Repository repo; setUp(() { repo = RepoMock(); // 给mock方法设置默认返回存根,避免非空类型报错 when(() => repo.getResetPasswordToken(any())) .thenAnswer((_) async => /* 构造测试用的GraphQLResponse实例即可 */); }); test("getResetPasswordToken调用验证", () { // 执行待验证的方法调用 repo.getResetPasswordToken("test@example.com"); // 验证方法被调用1次,这里必须传参实际调用方法 verify(() => repo.getResetPasswordToken(any())).called(1); }); }
注意:如果方法的参数是你自定义的非Dart内置类型,需要提前调用
registerFallbackValue(自定义类型的测试实例)注册fallback值,才能正常使用any()匹配参数,String、int这类内置类型不需要额外注册。
内容的提问来源于stack exchange,提问作者Cyrus the Great
相关产品推荐
相关产品推荐

