You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在pytest测试环境中接收第三方服务触发的Webhook?

在pytest中接收第三方触发的Webhook完成闭环测试

核心思路

不做模拟,直接在测试环境启动一个临时HTTP服务接收第三方发来的Webhook请求,等请求到达后再执行后续断言,实现完整的流程闭环。

具体实现步骤

1. 编写临时Webhook接收器的pytest夹具

用aiohttp搭建轻量临时服务,作为Webhook的接收端点,同时保存接收到的请求数据供测试验证:

import asyncio
import pytest
from aiohttp import web

@pytest.fixture
async def webhook_receiver():
    # 存储接收到的Webhook请求
    received_requests = []

    async def handle_webhook(request):
        # 读取请求体与头信息
        body = await request.json()
        received_requests.append({"body": body, "headers": dict(request.headers)})
        return web.Response(status=200)

    # 创建aiohttp应用并添加路由
    app = web.Application()
    app.add_routes([web.post("/webhook", handle_webhook)])

    # 启动临时服务,监听随机端口
    runner = web.AppRunner(app)
    await runner.setup()
    site = web.TCPSite(runner, "localhost", 0)  # 0表示自动分配可用端口
    await site.start()

    # 生成临时服务的Webhook地址
    base_url = f"http://localhost:{site._server.sockets[0].getsockname()[1]}"
    webhook_url = f"{base_url}/webhook"

    yield webhook_url, received_requests

    # 测试结束后清理服务
    await runner.cleanup()

2. 在测试函数中使用夹具完成闭环测试

拿到临时Webhook的URL后,配置给第三方服务(比如通过环境变量、配置项),发送请求后等待Webhook被接收,最后验证数据与业务结果:

import asyncio
from your_app import app, current_user
from httpx import AsyncClient

@pytest.mark.asyncio
async def test_user(client: AsyncClient, session, webhook_receiver):
    webhook_url, received_requests = webhook_receiver

    # 1. 配置第三方服务的Webhook地址为临时服务URL
    # 根据实际对接方式调整,比如设置环境变量或修改配置
    import os
    os.environ["THIRD_PARTY_WEBHOOK_URL"] = webhook_url

    # 2. 设置当前用户依赖
    app.dependency_overrides[current_user] = lambda: user1

    # 3. 发送请求触发第三方服务流程
    await client.post('/user/')

    # 4. 等待Webhook请求被接收(设置超时避免无限等待)
    try:
        await asyncio.wait_for(
            asyncio.get_event_loop().create_task(
                lambda: asyncio.sleep(0.1) while not received_requests
            ),
            timeout=10  # 超时时间根据第三方响应速度调整
        )
    except asyncio.TimeoutError:
        pytest.fail("未在规定时间内接收到Webhook请求")

    # 5. 验证Webhook内容是否符合预期
    received = received_requests[0]
    assert received["body"]["user_id"] == user1.id
    assert received["headers"].get("X-Signature") == "预期的签名串"  # 有签名验证时添加

    # 6. 验证Webhook处理后的业务结果,比如数据库状态
    db_user = await session.get(User, user1.id)
    assert db_user.status == "synced"

注意事项

  • 超时时间需根据第三方服务的实际响应速度调整,避免误判
  • 如果第三方服务需要Webhook有效性验证(如签名校验),临时接收器要对应实现逻辑
  • 若第三方为公网服务,需用内网穿透工具(如ngrok)让公网能访问到本地临时服务

内容的提问来源于stack exchange,提问作者tobias

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 23:35:22