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

Flutter-GraphQL:如何在单元测试中Mock watchQuery方法并提供Stub实现示例?

如何Stub Flutter-GraphQL的watchQuery方法

我之前也碰到过这个问题,确实因为ObservableQuery依赖QueryManager,直接Stub会有点绕。不过没关系,下面给你两种可行的实现方式,你可以根据自己的测试场景选择:

方式一:手动创建模拟的ObservableQuery

这种方式不需要依赖Mockito,适合快速搭建简单的Stub:

首先,我们自定义一个继承自ObservableQuery的模拟类,重写关键的stream属性来返回我们预定义的测试数据:

import 'package:graphql_flutter/graphql_flutter.dart';

class MockObservableQuery extends ObservableQuery {
  MockObservableQuery({
    required super.options,
    required super.queryManager,
  }) : super(
          link: MockLink(), // 用MockLink避免实际网络请求
          cache: InMemoryCache(), // 内存缓存,仅用于测试
        );

  // 重写stream,返回我们需要的测试结果
  @override
  Stream<QueryResult> get stream {
    // 模拟成功的查询结果,你可以根据测试需求修改data内容
    final testResult = QueryResult(
      data: {
        'user': {
          'id': '123',
          'name': 'Test User',
        }
      },
      source: QueryResultSource.network,
    );
    // 如果需要模拟多次数据发射,可以用Stream.fromIterable或者StreamController
    return Stream.value(testResult);
  }

  // 如果你需要测试refetch方法,也可以重写它
  @override
  Future<QueryResult> refetch() async {
    return QueryResult(
      data: {
        'user': {
          'id': '123',
          'name': 'Refetched Test User',
        }
      },
      source: QueryResultSource.network,
    );
  }
}

接下来,Stub你的GraphQLClient的watchQuery方法,让它返回这个模拟类的实例:

// 创建一个GraphQLClient实例(或者用你已有的实例)
final testClient = GraphQLClient(
  link: MockLink(),
  cache: InMemoryCache(),
);

// 如果你是在测试中替换原有的client,可以这样Stub:
// 假设你有一个依赖注入的client,或者直接在测试中替换
final stubbedWatchQuery = (WatchQueryOptions options) {
  return MockObservableQuery(
    options: options,
    queryManager: QueryManager(
      link: MockLink(),
      cache: InMemoryCache(),
    ),
  );
};

// 之后在测试中,当调用client.watchQuery时,就会返回我们的模拟实例

方式二:用Mockito来Mock(更灵活)

如果你的测试场景比较复杂,推荐用Mockito来Mock相关类,这样可以更灵活地控制返回结果:

首先,确保你已经在pubspec.yaml中添加了Mockito依赖,并且运行了代码生成命令(flutter pub run build_runner build)。

然后,生成MockGraphQLClient和MockObservableQuery:

// mockito生成的代码示例(你需要在test文件中添加@GenerateMocks注解)
import 'package:mockito/mockito.dart';

class MockGraphQLClient extends Mock implements GraphQLClient {}
class MockObservableQuery extends Mock implements ObservableQuery {}

接下来,在测试中配置Mock:

void main() {
  late MockGraphQLClient mockClient;
  late MockObservableQuery mockObservableQuery;

  setUp(() {
    mockClient = MockGraphQLClient();
    mockObservableQuery = MockObservableQuery();

    // 配置MockObservableQuery的stream返回测试数据
    when(mockObservableQuery.stream).thenAnswer((_) {
      final testResult = QueryResult(
        data: {'posts': [{'title': 'Test Post'}]},
        source: QueryResultSource.network,
      );
      return Stream.value(testResult);
    });

    // 配置GraphQLClient的watchQuery返回MockObservableQuery
    when(mockClient.watchQuery(any)).thenReturn(mockObservableQuery);
  });

  test('测试watchQuery的Stub行为', () async {
    // 调用watchQuery
    final query = mockClient.watchQuery(WatchQueryOptions(
      document: gql('query { posts { title } }'),
    ));

    // 订阅stream并验证结果
    expect(query.stream, emitsInOrder([
      predicate<QueryResult>((result) => result.data!['posts'][0]['title'] == 'Test Post')
    ]));
  });
}

关键注意点

  • 核心是让watchQuery返回的ObservableQuery的stream发出你需要的测试数据,因为业务逻辑通常是订阅这个stream来处理结果的。
  • 如果不需要完整的QueryManager功能,用MockLink和InMemoryCache就足够满足测试需求,避免依赖真实的网络或缓存实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 10:42:37