接口测试和单元测试到底有什么区别?别再傻傻分不清了

🔑 关键词:接口测试,单元测试,API测试,测试策略,自动化测试

📖 摘要:从真实工作场景出发,拆解接口测试和单元测试的本质差异,指出了多个新手容易踩的坑,并给出了具体的参数设计、断言和压测建议。

最近在带测试团队的时候,发现一个特别有意思的现象:很多人张口闭口说自己在做接口测试,结果点开他们的用例一看,基本就是拿着Postman调一下GET接口,然后看了看状态码是不是200,就喊通过了。这哪是接口测试,充其量叫接口能通测试。更离谱的是,有人把接口测试和单元测试混为一谈,觉得都是测一个函数,无非是个有网络一个没网络。这种认知误差直接导致很多系统上线后,线上故障频发,而测试报告却一片绿。

图片

我承认单元测试和接口测试确实有交叉地带,但它们的出发点完全不同。单元测试是开发为了验证自己写的那段逻辑,比如你写了一个计算折扣的函数,输入100元、会员等级3,预期返回85元,你只关心这个函数内部算得对不对。而接口测试关心的是两个服务之间、或者前端和后端之间的契约。举个例子,客户端调用/order/creat这个接口,传的JSON里有个字段叫discountType,结果你后端代码里根本没用这个字段,而是自己从数据库查了一个优惠券类型。单元测试时,你的代码逻辑没问题,返回值也对。可一旦前端把discountType传成“VIP专享”,后端却当成普通会员算,最终下单金额就是错的,而接口测试如果没覆盖到这种契约漏洞,测试照样是绿的。

图片

真正做过几年接口测试的人应该都有体会,最坑人的不是接口返回非200,而是返回200但业务上已经错了。我之前排查过一个订单回调问题,接口返回码是0,message是“成功”,可实际数据库里那笔订单的金额被覆盖成了0.01元。原因是上游接口重复请求,下游没有做幂等处理,同一个订单号处理了两次。用单元测试根本没法暴露这个问题,因为单测跑的是微服务内部的,根本不会用两个线程同时去调同一个业务方法。后来我们写接口测试时,专门设计了一个用例:同一个订单号并发提交两次,断言返回结果一致,且订单金额不变。跑完就发现必现重放问题。那段时间我逢人就说,接口测试真正要测的是系统对外的承诺,不是内部实现。

图片

如果你问我接口测试的参数设计具体怎么落地,我建议别老盯着边界值。边界值当然要测,但你还要测那种“半合法”的参数组合。比如分页接口,page_size在0到100之间校验是常规的,可是page_size=50,page_num=999999,这种组合往往就能暴露出慢查询或者超时。还有时间窗口类参数,比如起止时间,大部分人测了start>end的异常场景,却没测过start时间戳是负数、或者end是2099年这种超远时间,结果系统会傻乎乎地去扫描全表。我自己吃过这个亏:有个报表接口,传时间范围超过一年就卡死,后来在接口测试里加了一条断言——当时间跨度大于366天时,响应时间必须小于800ms,如果超时,则强制分页或拒绝查询。这种约束必须显式写进用例,才能防止开发以后悄悄放开限制。

图片

当然,接口测试的强势点是能直接压测出集群层面的问题,但这需要你注意一些容易被忽略的数字。比如你给HTTP客户端设置了connectTimeout=2000ms和readTimeout=5000ms,看起来挺合理吧,但如果你在接口测试里跑100个并发,服务端出现了线程池排队,个别请求的readTimeout就会超时。这种场景用单元测试根本模拟不出来,因为单测通常是不走网络协议的。更经典的是连接池耗尽:服务A调用服务B,B的响应平均时间从50ms变成了300ms,A的数据库连接池大小是20,接口测试时如果每秒请求量超过66个,连接池就直接被占满,然后开始报ConnectionPoolTimeout。这种问题只能在接口测试的持续性压测中暴露,而且你还要在用例里记录每个请求的耗时分布,不能只看平均耗时,要看TP99。

图片

最后说说断言到底该怎么写。如果你还停留在断言response.getCode() == 200,那真的不算会做接口测试。我的经验是至少要有四个层级的断言:第一层是协议层,状态码、响应时间、内容加密是否合法;第二层是业务层,返回的code、msg、data中的关键业务字段;第三层是数据层,比如调用了一个写接口,就要去数据库里查这条记录的状态、金额、更新时间,甚至要查流水表有没有多写或者漏写;第四层是依赖层,比如这个接口会调用一个消息队列,那还要断言消息是否投递成功、消费是否幂等。我之前遇到过一个场景,接口返回500,但业务操作其实已经成功了,原因是用例发起了重试,重试前没有做幂等校验,导致生成了两条重复的流水。所以现在的接口测试用例,我都会强行要求开发在接口里返回requestId,然后我们用这个requestId去追踪全链路,断言同一个requestId只对应一条核心流水。这套做法下来,我们线上重大bug减少了七成以上。说真的,接口测试这件事,你要是只做给领导看,那确实是Postman刷一刷就够了;但你要是想把系统质量兜住,就不能把“调通”当成“测完”。

图片