I'm trying to monkeypatch the external request. Here is the code of a web endpoint:
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)
When user sends a GET request to /test
, it requests an external API (JSONPlaceholder), gets the JSON result and adds 'foo' = 0
to it. After that it forwards the result back to the user.
Here is the Postman result:
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false,
"foo": 0
}
Next, here is my pytest
code:
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
I used pytest's monkeypatch
fixture to mock the HTTPX request's result with {"response": "response"}
.
So basically what I expected is that endpoint adds 'foo' = 0
to my mocked result. But instead it returned {"response": "response"}
unmodified.
Here's the traceback of pytest -vv
command:
> 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'}
Can someone help me with why the endpoint doesn't modify httpx.AsyncClient().get
mocked result?
I used sanic==22.9.0
for backend, httpx==0.23.0
for requests, and pytest==7.2.0
for testing.
Expected to get {'response': 'response', 'foo': 0}
instead got {"response": "response"}
- an unmodified result of mocked httpx response.