我正在尝试monkeypatch外部请求。下面是一个Web端点的代码:
import httpx, json
...
@app.get('/test')
async def view_test(request):
async with httpx.AsyncClient() as client:
# sending external request
api_response = await client.get(
f'https://jsonplaceholder.typicode.com/todos/1',
timeout=10,
)
resp = api_response.json()
# modifying the result
resp['foo'] = 0
# forwarding the modified result back to the user
return HTTPResponse(json.dumps(resp), 200)
当用户向/test
发送GET请求时,它会请求一个外部API(JSONPlaceholder),获取JSON结果并将'foo' = 0
添加到其中。然后,它会将结果转发回用户。下面是Postman结果:
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false,
"foo": 0
}
下面是我的pytest
代码:
import httpx, pytest
...
# The `client` parameter is the fixture of web app
def test_view_test(client, monkeypatch):
async def return_mock_response(*args, **kwargs):
return httpx.Response(200, content=b'{"response": "response"}')
monkeypatch.setattr(httpx.AsyncClient, 'get', return_mock_response)
_, response = client.test_client.get('/test')
assert response.json == {'response': 'response', 'foo': 0}
assert response.status_code == 200
我使用pytest的monkeypatch
fixture来模拟HTTPX请求的结果{"response": "response"}
,所以基本上我所期望的是端点将'foo' = 0
添加到模拟结果中,但是它返回的是未修改的{"response": "response"}
,下面是pytest -vv
命令的回溯:
> assert response.json == {'response': 'response', 'foo': 0}
E AssertionError: assert {'response': 'response'} == {'response': 'response', 'foo': 0}
E Common items:
E {'response': 'response'}
E Right contains 1 more item:
E {'foo': 0}
E Full diff:
E - {'foo': 0, 'response': 'response'}
E ? ----------
E + {'response': 'response'}
有人能帮我解释为什么端点不修改httpx.AsyncClient().get
模拟结果吗?我使用sanic==22.9.0
作为后端,httpx==0.23.0
作为请求,pytest==7.2.0
作为测试。
预期获得{'response': 'response', 'foo': 0}
,而不是获得{"response": "response"}
-模拟的httpx响应的未修改结果。
1条答案
按热度按时间cgfeq70w1#
问题是
sanic-testing
在幕后使用httpx
。所以,当你monkeypatchinghttpx
时,你也会影响测试客户端。因为你只想模拟传出的调用,我们需要排除那些受到影响的调用。我对@srbssv on Discord的评论是使用一个自定义函数monkeypatch httpx,该函数将检查请求的位置。如果是内部Sanic应用程序,则按原样继续。如果不是,则返回一个mock对象。
基本上是这样的: