集成测试是什么
集成测试验证模块之间、服务与外部依赖之间的协作是否成立:接口契约、数据流、事务边界与错误传递都在它的射程内。它位于测试金字塔中部——比单元测试真实(允许连数据库、消息队列等真实依赖),比端到端测试便宜(不经过完整界面链路)。集成测试要回答的核心问题不是某段逻辑对不对,而是拼装之后的数据与控制流对不对:接口参数被谁改写、事务何时提交、下游报错如何向上传递,这些只在组合场景才暴露,也正是它不可被单元测试替代的原因。
基本信息
| 验证对象 | 模块接口、服务契约、数据库与消息中间件交互 |
|---|---|
| 常用手段 | Testcontainers 起真实依赖、契约测试、契约桩服务 |
| 运行频率 | 提交级或每日构建,介于单元与 E2E 之间 |
| 真实度权衡 | 依赖越真实越可信,执行越慢越难高频运行 |
| 典型失败点 | 序列化格式、事务边界、超时与重试、幂等 |
典型使用场景
- 新增服务间调用:验证请求格式、响应解析与错误码约定
- 数据库迁移之后:验证新表结构下的读写路径与 ORM 映射
- 消息队列消费:投递、消费、重试与死信处理的完整环路
- 第三方 API 对接:先用契约桩固定行为,再做真实联调
- 跨服务事务与补偿:确认提交顺序与失败回滚符合业务预期
- 网关与限流配置:路由规则、超时、重试策略在真实链路中的组合行为
- 缓存与数据库一致性:写后读、失效策略在组合下的表现
Python 集成测试片段
Python 集成测试片段
# 连接真实数据库会话与测试客户端,验证下单链路
def test_create_order_persists(db_session, client):
resp = client.post('/orders', json={'sku': 'A-1', 'qty': 2})
assert resp.status_code == 201 # 接口层返回创建成功
order = db_session.get(Order, resp.json()['id'])
assert order.qty == 2 # 数据确实落库
assert order.status == 'pending' # 初始状态符合契约依赖真实度阶梯
| 方式 | 真实度 | 速度 | 适用阶段 |
|---|---|---|---|
| 内存替身(mock) | 低,不连真实依赖 | 最快 | 单元层,不属于集成测试 |
| 嵌入式数据库/内存队列 | 中 | 快 | 快速集成冒烟,提交级 |
| Testcontainers 真实容器 | 高 | 中 | 提交级或每日构建的集成测试 |
| 共享测试环境 | 最高 | 慢 | 发布前的端到端前序验证 |
用大量 mock 拼出来的集成测试只验证了替身行为:结论看似通过,真实联调仍然失败。判断标准是这条用例是否连接了真实依赖或真实契约。
集成测试的失败大多不是逻辑错误,而是契约漂移:字段名、类型、枚举值在两侧悄悄变化,直到联调期才集中爆发;把契约校验前置到构建或启动阶段,能显著缩短排查路径。
运行时长控制技巧:容器夹具按会话级复用、用例按依赖分组调度,其余并行执行;把集成层稳定控制在几分钟内,它才有资格挂在提交级流水线上。
观察点建议:除了断言最终状态,还应断言关键中间产物(发出的消息、写入的日志字段、调用的下游接口),中间环节的静默错误才藏不住。
数据隔离是集成测试的头号工程问题:每个用例使用独立事务回滚、独立 schema 或按用例命名空间造数据,避免并发执行互相污染;契约测试(消费者驱动契约)则与集成测试互补,让提供方改动在提交阶段就暴露对消费方的影响。