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
相关产品推荐
相关产品推荐

