我厌倦了在 pytest 中 Mock API,于是我构建了更简洁的方式。

发布: (2026年3月8日 GMT+8 23:01)
5 分钟阅读
原文: Dev.to

Source: Dev.to

Cover image for I Got Tired of Mocking APIs in pytest. So I Built a Cleaner Way.

Sherin Joseph Roy

如果你在 Python 中编写集成测试已经有一段时间,你一定遇到过这个问题。

你的测试调用了三个外部服务。
你模拟一个端点。
然后是另一个。
再然后是另一个。

突然间,你的测试变成了 60 行,而且一半都是 patch。

此时你已经不再测试行为,
而是在维护脚手架。

我在处理服务间调用流程时反复遇到这种情况,尤其是当:

  • 单个操作触发多个 HTTP 调用
  • 不同的测试需要不同的响应组合
  • fixture 开始变成小型框架

工具生态非常完善——responsesunittest.mock、httpx 的模拟工具——但一旦端点数量增加,可用性就会下降。

问题不在于能力,
而在于可读性。

临界点

以下是多端点模拟常见的情况:

import responses

@responses.activate
def test_checkout():
    responses.add(
        responses.GET,
        "https://api.example.com/users/1",
        json={"id": 1, "name": "Alice"},
        status=200,
    )

    responses.add(
        responses.POST,
        "https://api.example.com/orders",
        json={"order_id": 42},
        status=201,
    )

    result = checkout_flow()
    assert result.success

这在小范围下可以工作。但如果扩展的话:

  • 每个测试的不同组合
  • 条件响应
  • 动态负载
  • 部分 URL 匹配
  • 多个外部服务

现在你的 fixture 增多。帮助函数增多。补丁遍布各处。测试变成了基础设施。

我想要的替代方案

我想要的东西是:

  • 自然地运行在 pytest
  • 将 mock 与测试逻辑保持靠近
  • 使多端点流程易读
  • 避免启动测试服务器
  • 避免深层补丁树

于是我构建了一个名为 api‑mocker 的小工具。

理念很简单:最小的表面面积。没有笨重的 DSL。没有框架抽象。只有显式的端点声明。

api‑mocker 插图

示例

def test_checkout_flow(api_mocker):
    api_mocker.get("/users/1").respond_with(
        status=200,
        json={"id": 1, "name": "Alice"},
    )

    api_mocker.post("/orders").respond_with(
        status=201,
        json={"order_id": 42},
    )

    result = checkout_flow()
    assert result.success
  • 没有装饰器。
  • 没有激活上下文。
  • 没有分散的补丁逻辑。

测试夹具负责每个测试的生命周期和清理。

设计原则

每个测试的隔离

Mocks 在每个测试后自动重置。没有共享状态泄漏。

明确的失败

  • 如果未调用预期的端点,测试失败。
  • 如果调用了意外的端点,测试失败。

沉默的成功会隐藏集成问题。

轻量级拦截

没有嵌入式服务器。没有进程开销。拦截发生在请求层。

interception diagram

此方法最适用的场景

  • 微服务架构
  • 调用多个第三方 API 的服务
  • 支付或认证流程
  • 编排式后端

只要单个流程涉及两个或多个 HTTP 集成的任何地方。

我正在探索的未解之问

Mocking 库始终在简洁性与灵活性之间保持张力。我正在积极思考的几个方向:

  • 异步客户端处理
  • 流式响应
  • 在何种情况下应让 Mocking 让位于契约测试
  • 在大型测试套件中检测过度 Mock

这些权衡会影响长期的测试质量。

未来想法

为什么我要分享这个

Mocking 策略直接影响代码库的健康。
可读的测试具有可扩展性,Fixture 丛林则没有。

如果你在 Python 中处理过混乱的多端点集成测试,我真诚地想听听:

  • 哪些做得好
  • 哪些出现了问题
  • 何时转向了契约测试

项目链接(如果你想了解实现细节):

  • PyPI:
  • GitHub:
0 浏览
Back to Blog

相关文章

阅读更多 »