Litestar API测试:如何正确Mock内部调用的get_token异步函数?
解决Mock未生效的问题
你的Mock未生效的核心原因是patch的目标路径错误。在Python中,mock需要针对被测试代码实际引用的对象进行替换,而不是原函数的定义位置。
问题分析
在app/token/routes.py中,你应该是通过from app.service import get_token导入了get_token函数。此时routes.py模块内部会创建一个指向该函数的本地引用。你的测试中patch了app.service.get_token,但这只会修改原模块中的函数,不会影响routes.py中已经导入的本地引用,因此真实的网络请求仍然会被触发。
正确的解决方案
1. 修改patch目标路径
将patch的目标改为app.token.routes.get_token,也就是get_token在routes.py中的引用位置。
2. 简化Mock设置
不需要额外创建AsyncMock并设置side_effect,直接在传入的get_token_mock上设置return_value即可。
3. 构造符合预期的Mock响应
需要模拟httpx.Response对象的text属性,确保后续的json.loads能正常解析。
修正后的测试代码
# tests_token/test_routes.py import pytest from unittest import mock from httpx import AsyncTestClient from app import app # 定义模拟的请求和响应内容 TOKEN_DATA = {"token": "test-token"} MOCK_RESPONSE_TEXT = '{"idToken": "mock-id-token", "refreshToken": "mock-refresh-token"}' @pytest.mark.asyncio class TestTokenController: @mock.patch("app.token.routes.get_token", new_callable=mock.AsyncMock) async def test_check_token(self, get_token_mock): # 构造模拟的响应对象 mock_response = mock.MagicMock() mock_response.text = MOCK_RESPONSE_TEXT get_token_mock.return_value = mock_response async with AsyncTestClient(app=app) as client: response = await client.post("/check-token", json=TOKEN_DATA) # 验证Mock被正确调用 get_token_mock.assert_called_once_with(token="test-token") # 验证响应状态和内容 assert response.status_code == 200 response_json = response.json() assert response_json["idToken"] == "mock-id-token" assert response_json["refreshToken"] == "mock-refresh-token"
额外说明
- 若需要模拟异常场景(如网络连接失败),可以通过
get_token_mock.side_effect抛出对应异常,例如get_token_mock.side_effect = httpx.ConnectError。 - 确保模拟响应的结构与真实接口返回一致,避免JSON解析失败。
内容的提问来源于stack exchange,提问作者maskalev
相关产品推荐
相关产品推荐

