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

Monkeypatch Mock httpx外部请求后,接口未修改返回结果求助

排查Sanic接口模拟外部请求后未添加指定字段的问题

以下是几个可能导致问题的原因及对应的解决方法:

1. 模拟的httpx.AsyncClient.get返回值结构错误

httpx.AsyncClient.get实际返回的是**httpx.Response对象**,而非直接的字典。如果你的测试代码直接让模拟方法返回{"response": "response"},接口代码中调用response.json()时会抛出异常,但从你描述的现象来看,更可能是你误将模拟的字典直接返回,跳过了后续添加字段的逻辑。

正确的模拟方式应该返回带有异步json()方法的Mock对象:

async def mock_get(*args, **kwargs):
    class MockResponse:
        async def json(self):
            return {"response": "response"}
    return MockResponse()

monkeypatch.setattr(httpx.AsyncClient, 'get', mock_get)

2. 接口代码中添加字段的逻辑存在疏漏

检查你的接口实现,确认是否正确保存了修改后的字典并返回:

  • 错误示例1:修改临时对象后未保存
# 错误:修改的是response.json()返回的临时字典,未赋值给变量
await response.json()['foo'] = 0
return json(await response.json())
  • 错误示例2:返回原始数据而非修改后的字典
data = await response.json()
data['foo'] = 0
return json(await response.json())  # 这里又重新获取了原始数据

正确的写法应该是:

data = await response.json()
data['foo'] = 0
return json(data)

3. Monkeypatch的时机或目标对象错误

确保你是在创建Sanic测试客户端之前完成的Monkeypatch操作,否则实例化的AsyncClient不会使用补丁后的方法。另外,确认补丁的是httpx.AsyncClient.get(类方法),而非实例的get方法——只要补丁在实例化前完成,类方法的补丁会作用于所有新创建的实例。

验证步骤

  1. 在接口代码中打印data变量,确认'foo':0是否已被正确添加;
  2. 在测试代码中检查Mock对象的结构,确保json()方法能返回预期字典;
  3. 确认Monkeypatch操作在测试客户端初始化前执行。

参考示例代码

接口实现

from sanic import Sanic, json
import httpx

app = Sanic("TestApp")

@app.get('/test')
async def test_handler(request):
    async with httpx.AsyncClient() as client:
        resp = await client.get("https://jsonplaceholder.typicode.com/todos/1")
        data = await resp.json()
        data['foo'] = 0
        return json(data)

测试代码

import pytest
from sanic.testing import TestClient
from your_app import app
import httpx

@pytest.mark.asyncio
async def test_test_endpoint(monkeypatch):
    async def mock_get(*args, **kwargs):
        class MockResponse:
            async def json(self):
                return {"response": "response"}
        return MockResponse()
    
    monkeypatch.setattr(httpx.AsyncClient, 'get', mock_get)
    
    async with TestClient(app) as client:
        resp = await client.get('/test')
        data = await resp.json()
        assert data == {"response": "response", "foo": 0}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 14:50:31