实际与Mock查询参数匹配,但Mockito的thenAnswer未调用且报类型错误
我编写了一个测试用例测试addToCart方法,该方法会间接调用computeVoucher方法。computeVoucher会调用GraphQL客户端的API,测试中已用Mockito对该客户端做了Mock处理。实际查询与Mock的参数匹配,但thenAnswer方法未被触发,同时报错:Error: Null is not a type of Future。
相关代码
test.dart
test('When only voucher is added and exceeds cart total', () async { final Cart cart = Cart(); cart.voucher = Voucher('test12345', true, 'Flat', 250, 1, 250, client: mockClient, id: '12345'); await cart.addToCart(product); expect(cart.pricingSummary.totalAmount, 0.0); });
voucher.dart
Future<int?> computeVoucher( String? voucherId, List cartProducts) async { Map<String, dynamic> variables = { 'voucherId': voucherXid, 'cartProducts': CartProduct.getProducts(false, cartProducts), 'cartLineItems': CartProduct.getProducts(true, cartProducts) }; Map<String, dynamic> result = await (client! .query(query: computeVoucherQuery, variables: variables)); return result['computeVoucherDiscount'].toInt(); }
voucher_mock.dart
Future query( {required String query, var variables, bool networkOnly = true}) async { when(_client.query(QueryOptions( document: gql(computeVoucher['query']), variables: computeVoucherVariables, fetchPolicy: FetchPolicy.networkOnly))) .thenAnswer((realInvocation) async => MockQueryResult(data: computeVoucher['response'])); }
问题分析与修复方案
1. Mock参数匹配逻辑不匹配
你在voucher_mock.dart的when调用中,使用computeVoucherVariables作为匹配参数,但实际computeVoucher方法传入的是动态生成的variables对象。由于两个对象引用不同,Mockito无法匹配到调用,返回默认的null,进而抛出"Null is not a type of Future"错误。
修复方式:
使用any匹配变量,或者确保computeVoucherVariables和实际生成的variables内容完全一致(包括键值对顺序和内容)。用any的修改示例:
when(_client.query(QueryOptions( document: gql(computeVoucher['query']), variables: anyNamed('variables'), fetchPolicy: FetchPolicy.networkOnly))) .thenAnswer((_) async => MockQueryResult(data: computeVoucher['response']));
2. computeVoucher方法参数错误
voucher.dart的variables中使用了voucherXid,但方法参数是voucherId,这会导致变量值不匹配,影响Mock的匹配逻辑。需要将voucherXid改为voucherId:
Map<String, dynamic> variables = { 'voucherId': voucherId, 'cartProducts': CartProduct.getProducts(false, cartProducts), 'cartLineItems': CartProduct.getProducts(true, cartProducts) };
3. Mock初始化时机问题
voucher_mock.dart里的query方法是自定义方法,但Mockito的when配置应该放在测试初始化阶段(比如setUp方法中),确保测试用例执行前就完成Mock逻辑的设置。
4. 空值安全处理
computeVoucher方法中直接对result['computeVoucherDiscount']调用toInt(),如果该值为null或非数值类型会报错。建议添加空检查:
return result['computeVoucherDiscount']?.toInt();
内容的提问来源于stack exchange,提问作者aki

