Files
ReelShort/test/support/fake_http_adapter.dart
T
Vicky 1853e1845c refactor(client): 网络层由官方 http 换成 dio(对外行为不变)
为什么:权威文档(AGENTS.md / CODING_STANDARDS.md)强制网络层用 dio,差异清单 A 组第 1 题
用户裁定选 A;原来用官方 http 是在无文档状态下按口头要求选的。

- ApiClient 改用 dio + BaseOptions(validateStatus 恒真、8s 超时、ResponseType.bytes 自行 UTF-8 解码)
- 新增 AuthHeaderInterceptor(Authorization / X-Device-Id)与 EnvelopeInterceptor
  (解包 {code,message,data} + 错误码映射 + 401 判定)
- 401 → 刷新 → 重发一次在 ApiClient 里编排,刻意不放在拦截器内重发:dio 的排队拦截器
  在回调里再发请求会自锁
- 接口层(auth_api/catalog_api)签名、全部 controller/logic/page 未改动
- 测试:新增假 dio adapter 替代 MockClient,断言口径一条未改;用例名改为 should_<期望>_when_<条件>;
  新增 api_client_test(解包/错误映射/请求头/查询参数/跳过重试)与 live_auth_test(真实后端 POST 链路)
- pubspec:加 dio、移除已无引用的 http
- 实测:dart analyze lib test 零告警;flutter test 155 全过;真实联调(8081)GET/POST 链路均通
2026-10-16 09:30:46 +08:00

47 lines
1.2 KiB
Dart

// Author: fruit.com.cn
import 'dart:convert';
import 'dart:typed_data';
import 'package:dio/dio.dart';
/// 假响应:[body] 会按 UTF-8 编码成字节,[statusCode] 默认 200。
class FakeHttpResponse {
FakeHttpResponse(this.body, [this.statusCode = 200]);
final String body;
final int statusCode;
}
/// dio 的测试替身:把请求交给回调处理,全程不联网。
///
/// 顺带记录每个收到的请求,测试可以直接断言"发了几次、带了什么头"。
class FakeHttpAdapter implements HttpClientAdapter {
FakeHttpAdapter(this.handler);
final Future<FakeHttpResponse> Function(RequestOptions options) handler;
/// 按顺序记录收到的请求,用于断言请求次数与请求头。
final List<RequestOptions> requests = [];
@override
Future<ResponseBody> fetch(
RequestOptions options,
Stream<Uint8List>? requestStream,
Future<void>? cancelFuture,
) async {
requests.add(options);
final response = await handler(options);
return ResponseBody.fromBytes(
utf8.encode(response.body),
response.statusCode,
headers: const {
'content-type': ['application/json; charset=utf-8'],
},
);
}
@override
void close({bool force = false}) {}
}