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

实际与Mock查询参数匹配,但Mockito的thenAnswer未调用且报类型错误

问题:Mockito Mock的GraphQL客户端未触发thenAnswer,抛出"Null is not a type of Future"错误

我编写了一个测试用例测试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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 14:54:53