接口测试
2026/8/21大约 9 分钟
接口测试
1 什么是接口测试?为什么要做接口测试?
- 直接对服务端 API 进行测试,验证请求参数、响应数据、状态码、逻辑与异常处理是否正确。
- 优点:比 UI 测试更早介入、更稳定、执行快、成本低,能发现 UI 层发现不了的问题(如数据错误、越权、参数校验缺失)。
HTTP 常见状态码及含义?
- 200 OK;201 Created;204 No Content。
- 301 永久重定向;302 临时重定向;304 Not Modified。
- 400 参数错误;401 未认证;403 无权限;404 不存在;405 方法不允许;409 冲突;422 参数校验失败。
- 500 服务器内部错误;502 网关错误;503 服务不可用;504 网关超时。
GET 和 POST 的区别?
- GET:参数在 URL 上、有长度限制、可缓存、只读语义(不应修改服务端数据)、不安全(会留在历史记录)。
- POST:参数在 body、无长度限制、不缓存、可修改服务端数据。
- 实际差异还取决于实现;RESTful 语义中 GET 幂等、POST 不幂等。
如何保证接口测试的幂等性测试?
- 幂等:多次执行与一次执行结果一致。对 POST/PUT/DELETE 设计重复请求用例,验证重复提交不会产生重复数据、不报错、返回一致。
- 常见实现:唯一请求 ID、数据库唯一索引、分布式锁、乐观锁。
什么是 Token 鉴权?JWT 的结构?
- 客户端登录后获得 token,后续请求携带(通常放 Authorization 头)。
- JWT 三段式:
Header.Payload.Signature:- Header:算法与类型(
{"alg":"HS256","typ":"JWT"})。 - Payload:声明(sub、exp、iat、自定义字段)。
- Signature:
HMACSHA256(base64(Header).base64(Payload), secret)。
- Header:算法与类型(
- 特点:无状态、可跨域;但 payload 只做 base64 编码非加密,敏感信息不能放。
接口测试中发现哪些典型缺陷?
- 参数校验缺失(必填、类型、长度、格式、枚举)、
- 越权(水平/垂直)、
- 返回码错误、
- 响应字段缺失/多余、
- 并发导致数据不一致、
- 空值/超大值导致 500、
- SQL 注入等安全漏洞、超时无兜底。
接口自动化框架如何搭建?(高频)
- 技术栈:Python Requests/Pytest 或 Java RestAssured/TestNG。
- 分层:用例层(yaml/excel/json 驱动)→ 核心封装层(request 封装、断言封装)→ 数据层(测试数据管理)→ 报告层(Allure)→ CI 集成(Jenkins)。
- 核心能力:token 自动管理、参数化、用例依赖处理(如先登录)、数据库断言、Mock 服务。
如何做接口的并发测试?
- 用 Locust(Python)/ JMeter / 自研多线程工具模拟并发请求。
- 关注点:并发下数据正确性(重复下单、超卖)、接口稳定性(超时、500)、资源消耗(连接数、线程池)、锁与事务隔离。
什么是 Mock?什么时候用?
- Mock 是用可控的假实现替换真实依赖(
第三方接口、未开发完的服务、支付网关等)。 - 适用:依赖未就绪、环境不稳定、构造异常数据困难、需要模拟超时/失败/限流等异常场景。
- 工具:Python
unittest.mock、responses、WireMock、Moco、Mockserver。
WebSocket 如何测试?与 HTTP 的区别?
- WebSocket 是全双工长连接,服务端可主动推送;HTTP 是请求-响应模式。
- 测试:建立连接(含鉴权)、消息收发、心跳保活、断线重连、并发连接数、消息乱序/丢失。
- 工具:
websocket-client(Python)、Postman、wscat、JSR356 客户端。
2 微服务架构下的RPC接口测试
Dubbo RPC 接口测试和 HTTP 接口测试最大的区别是:它不走 HTTP 协议,无法用 Postman/Burp 直接打。RPC 是"服务间直连"(TCP 长连接 + 自定义协议 + (nacos & eruka)注册中心寻址),而 Gateway 只是 HTTP 入口。存在以下挑战:
- 服务依赖:服务众多,依赖关系错综复杂,环境搭建困难
- 数据一致性:测试数据需要在多个服务间保持一致性
- 版本兼容:服务独立部署,版本兼容性测试变得重要
用户 → Gateway(HTTP: 鉴权/限流/路由) → Consumer(业务服务) --Dubbo RPC--> Provider(核心服务)
└──────── 注册中心(Nacos/ZK) ────────┘2.1 微服务架构中,你是怎么做测试计划的?
- 测试目标 → 策略
| 你要验证什么 | 首选策略 | 说明 |
|---|---|---|
| RPC 协议/序列化/异常传播 | L0 | 进程内即可验证协议本质 |
| 边界值/性能预算 | L0 | 确定性高、易构造 |
| 服务注册/发现/负载均衡 | L1 | 必须过真实 Nacos |
| 配置一致性(端口/超时/namespace) | L1 | 真实配置加载 |
| HTTP→Dubbo 协议转换 | L2 | 网关桥接层专属 |
| 错误码→HTTP 状态码映射 | L2 | 网关专属 |
| 全链路用户路径 | L2 | 发版前验收 |
测试场景 -> 技术选型
| 场景 | 推荐入口 |
|---|---|
| 内部服务间契约测试 / 单元回归 | Java 原生调用 |
| 契约模块签名回归 | Java 原生调用(编译期暴露变更) |
| 测试平台 / 自动化脚本调任意接口 | 泛化调用 |
| HTTP 网关桥接 / 外部系统对接 | 泛化调用 |
| 跨语言(Go/Python/Node 调 Dubbo) | 泛化调用 |Java原生调用 与 泛华动态调用 对比
//JAVA原生调用
ReferenceConfig<UserDubboService> ref = new ReferenceConfig<>();
ref.setInterface(UserDubboService.class);
UserDubboService svc = ref.get();
UserInfoDTO dto = svc.getById(1L); // 编译期类型安全优势
- 类型安全:编译期校验方法与参数,IDE 自动补全,避免手写字符串拼错。
- 性能高:直接类型化代理调用,无泛化反射开销。
- 可读性好:调用即普通 Java 方法,断言直观。
- 契约回归快:接口签名变更时编译即失败,第一时间暴露。
劣势
- 必须引入接口包:Consumer 需要依赖
dubbo-api契约模块,跨语言/外部系统无法使用。 - 紧耦合:本地调用方与 Provider 编译期强绑定,契约演进影响面大。
- 无法动态调用未知接口:不适用于测试平台「任意接口任意方法」的场景。
GenericService svc = (GenericService) ref.get();
Object result = svc.$invoke("getById", new String[]{"java.lang.Long"}, new Object[]{1L});优势
- 无需接口包:Consumer 可不依赖
dubbo-api,实现跨语言/跨团队/动态调试。 - 动态性强:方法名 + 参数类型 + 参数值全部运行时传入,可调任意接口。
- 天然适配测试平台:HTTP 网关桥接、脚本化测试、快速联调的首选入口。
- 契约解耦:服务端接口演进不影响泛化调用方(弱类型)。
劣势
- 无类型安全:方法名/参数类型字符串易拼错,只能在运行期发现。
- 性能略低:反射 + 动态路由,有轻微额外开销(常规调用可忽略)。
- 可读性差:
$invoke调用链较晦涩,断言需对 Map/Object 手工解析。 - 参数映射易错:复杂嵌套 DTO/泛型需手动构造 Map,与原生对象映射存在偏差风险。
鉴于微服务架构中的接口特点,【给你一个user-service微服务】你是如何测试 dubbo rpc 接口?
设计「契约 → 集成 → 端到端」三层测试策略。
- 不同层的测试策略及测试覆盖的场景
| 策略 | 速度 | 成本 | 确定性 | 覆盖深度 | 何时用 |
|---|---|---|---|---|---|
| L0 契约(使用Java原生调用,进程内直连) | ★★★★★ | ★★★★★ 低 | ★★★★★ 高 | RPC 协议/异常/边界 | 每次提交/CI 必跑 |
| L1 集成(Nacos 发现) | ★★★ | ★★★ 中 | ★★★ 中 | 注册中心/真实调用链 | 中间件就绪的回归 |
| L2 端到端(HTTP 网关桥接) | ★ | ★ 高 | ★★ 低 | 全链路/协议转换/错误码 | 发版前/全链路验收 |
L0 契约测试(进程内双端直连)
优势
- 零外部依赖:不需要 Nacos/MySQL/Spring 容器,
mvn test一键跑,CI 稳定、无中间件抖动。 - 速度最快:进程内直连,毫秒级完成全部 20 个用例。
- 确定性最高:数据层 Mock,用例 100% 可复现,无并发/网络/环境干扰。
- 覆盖 RPC 本质:验证真实 Dubbo 协议(协议编解码、序列化、泛化调用
$invoke、异常跨 RPC 传播)。 - 能测到真正的边界:null/空串/超长串/最大值等极端输入,以及性能预算断言。
劣势
- 覆盖不到注册中心:不经过 Nacos,无法验证服务发现、负载均衡、路由。
- 数据层是 Mock:不验证真实 MyBatis-Plus 映射与 SQL,契约正确 ≠ 数据库正确。
- 无 HTTP 层:不覆盖网关过滤、参数校验、错误码→HTTP 状态码映射。
- 可能产生「假绿」:Mock 配置与真实 Mapper 行为不一致时,用例通过但线上仍出问题。
适用:开发提交流水线、TDD 红绿灯、协议与异常语义回归。
L1 集成测试(Nacos 服务发现)
优势
- 验证真实注册链路:Provider 注册 → Consumer 经 Nacos 发现 → 真实 RPC,补足 L0 盲区。
- 贴近生产配置:
@ActiveProfiles("dev")走真实配置,能发现配置不一致、端口/超时问题。 - 可测服务间契约一致性:
existsByUsername ↔ getByUsername等跨方法一致性断言。 - 成本适中:只依赖 Nacos + MySQL,比 L2 轻。
劣势
- 依赖中间件:需先起 Nacos + MySQL + user-service,环境编排成本高、易抖动。
- 执行慢:Spring 容器启动 + 网络 RPC,单测耗时是 L0 的几十倍。
- 确定性下降:依赖注册中心状态,偶发服务未注册/网络波动导致 flaky。
- 无 HTTP 网关层:仍不覆盖网关桥接与错误码 HTTP 化。
适用:中间件可用的回归测试、服务注册/发现改动后的验证、跨服务契约联调。
L2 端到端测试(HTTP 网关泛化桥接)
优势
- 全链路覆盖:HTTP → 网关 → 泛化桥接 → Dubbo Provider → DB,最接近用户真实路径。
- 验证协议转换与错误码映射:JSON 参数映射、404/400/502 错误码语义,是 L0/L1 都无法覆盖的。
- 真实数据库:走真实 UserMapper 与 SQL,数据正确性得到验证。
- 接口契约即文档:
/api/dubbo/invoke的请求/响应 JSON 可直接作为外部对接契约。
劣势
- 依赖最重:需要 Nacos + user-service + gateway 全栈在线,环境搭建成本最高。
- 最慢最不稳:跨多进程 + 网络 + DB,耗时长,且任一环节抖动即失败(flaky 高风险)。
- 排障困难:问题可能出在任意一层(网关/桥接/Dubbo/DB),定位成本高。
- 难以覆盖所有分支:全链路条件下难以系统构造边界/异常输入,覆盖密度最低。
适用:发版前全链路验收、外部集成方联调、网关桥接功能验证。