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

使用Mockito测试Flutter Riverpod AsyncValue时遇非Mockito对象错误

问题原因与解决方法

报错“Used on a non-mockito object”的核心原因是你的Listener<T>泛型类没有被Mockito正确识别为mock对象,通常是因为泛型类继承Mock的方式在当前Mockito版本下不兼容,或者Mockito没有正确生成call方法的mock实现。

下面是具体的解决步骤:

1. 替换自定义Listener类,直接创建函数类型的Mock

放弃自定义的Listener<T>类,直接用Mockito提供的方式创建符合签名的mock函数,避免泛型继承带来的问题:

import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:riverpod/riverpod.dart';

void main() {
  group('GeoData', () {
    test('initialization with default GeoInfo data', () {
      final container = ProviderContainer();
      addTearDown(container.dispose);
      // 直接创建对应签名的mock函数
      final listener = mock<void Function(AsyncValue<GeoInfo>?, AsyncValue<GeoInfo>)>();

      container.listen(geoDataProvider, listener, fireImmediately: true);

      // 直接验证调用,不需要箭头函数包裹
      verify(listener(null, const AsyncData<GeoInfo>(GeoInfo.empty())));
      verifyNoMoreInteractions(listener);
    });
  });
}

2. 若坚持使用自定义Listener类,改用Mockito代码生成

如果一定要保留自定义的Listener类,需要使用Mockito的代码生成功能(适配Mockito 5+版本):

步骤1:添加依赖到pubspec.yaml

dev_dependencies:
  flutter_test:
    sdk: flutter
  mockito: ^5.4.0
  build_runner: ^2.4.4

步骤2:创建mock生成文件

比如创建test/mocks.dart:

import 'package:mockito/mockito.dart';
import 'package:riverpod/riverpod.dart';

// 生成泛型Listener的mock类
@GenerateMocks([], customMocks: [
  MockSpec<Listener<AsyncValue<GeoInfo>>>(
    as: #MockGeoInfoListener,
  )
])
void main() {}

步骤3:运行代码生成命令

在终端执行:

flutter pub run build_runner build

步骤4:在测试中使用生成的mock类

import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:riverpod/riverpod.dart';
import 'mocks.dart'; // 导入生成的mock文件

void main() {
  group('GeoData', () {
    test('initialization with default GeoInfo data', () {
      final container = ProviderContainer();
      addTearDown(container.dispose);
      // 使用生成的mock类
      final listener = MockGeoInfoListener();

      container.listen(geoDataProvider, listener, fireImmediately: true);

      verify(() => listener(null, const AsyncData<GeoInfo>(GeoInfo.empty())));
      verifyNoMoreInteractions(listener);
    });
  });
}

3. 额外检查点

  • 确保GeoInfo类正确实现了==运算符和hashCode方法,否则AsyncData<GeoInfo>的实例对比会失败,导致验证不通过(虽然这不是当前报错的直接原因,但会引发后续问题)。
  • 确认Mockito版本与Flutter/Dart版本兼容,避免版本不匹配导致的mock失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 09:42:39