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

如何编写Dio超时单元测试 解决Mockito模拟Dio报错问题

测试失败根因定位

对照测试输出的报错信息,两个核心问题导致测试未按预期运行:

  • 模拟Dio抛错的方法配置完全错位
  • 实际抛出的对象是闭包而非预期的DioError实例
    从报错日志threw <Closure: (dynamic) => DioError>可以直接验证:你给thenThrow传的不是异常本身,而是一个返回DioError的匿名函数,Mockito会直接把这个匿名函数当异常抛出,根本无法命中数据源里on DioError catch(e)的捕获逻辑。
问题修正步骤

1. 修正Mockito的抛错配置

thenThrow方法的入参规则是直接传入需要抛出的异常实例,不需要包一层返回异常的函数。你之前错误地按照thenAnswer的写法给thenThrow传了闭包,这是核心错误来源。
同时注意:5.x版本以上的Dio构造DioError时必须传入关联的RequestOptions,否则会触发内部参数校验异常,影响测试结果。
错误写法:

when(mockDio.post(paths.login, data: tParams.toJson())).thenThrow(
    (_) async => DioError(type: DioErrorType.CONNECT_TIMEOUT));

修正后的写法:

// 构造符合Dio内部校验规则的CONNECT_TIMEOUT类型DioError
final connectTimeoutError = DioError(
  type: DioErrorType.CONNECT_TIMEOUT,
  requestOptions: RequestOptions(path: paths.login),
);
when(mockDio.post(paths.login, data: tParams.toJson()))
    .thenThrow(connectTimeoutError);

2. 调整异步测试的断言逻辑

因为被测的login方法是异步返回Future的,直接同步传递闭包的写法容易出现Future未完成的状态识别偏差,改成async模式的断言写法更稳妥。
修改后的完整可运行测试代码:

test(
  'Should throw [ConnectTimeOutException] when reach timeout',
  () async {
    // arrange
    when(mockNetworkInfo.isConnected).thenAnswer((_) async => true);
    // 构造符合Dio规则的超时类DioError
    final connectTimeoutError = DioError(
      type: DioErrorType.CONNECT_TIMEOUT,
      requestOptions: RequestOptions(path: paths.login),
    );
    when(mockDio.post(paths.login, data: tParams.toJson()))
        .thenThrow(connectTimeoutError);

    // act + assert 合并,直接对异步方法做异常捕获校验
    expect(
      () async => loginDataSource.login(params: tParams),
      throwsA(isA<ConnectTimeOutException>()),
    );
  },
);
常见踩坑提醒
  • 严格区分Mockito的thenAnswer和thenThrow用法:
    • thenAnswer:传入一个函数,函数返回值是mock方法的正常返回结果,用于模拟异步/带返回值的方法逻辑
    • thenThrow:直接传入要抛出的异常实体,用于模拟方法抛错的场景
  • 模拟Dio的异常时,构造DioError必须匹配当前Dio版本的必填参数要求,否则即使模拟逻辑正确,构造异常的过程本身就会触发非预期报错
  • 参数匹配时要确保when子句里的入参和实际数据源调用时的入参完全一致,否则mock规则不会命中,会走真实的Dio网络请求逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.28 16:36:04