When masking httpx.AsyncClient with unittest.mock in Pytest, AsyncMock must be used instead of MagicMock for async methods like post/get to prevent TypeError when awaited.
64
76%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./.agent/skills/pytest-asyncio-httpx-mocking/SKILL.mdpatch.object(httpx.AsyncClient, 'post', return_value=mock_response)。response = await client.post(...) 的地方抛出 TypeError: object MagicMock can't be used in 'await' expression。httpx.AsyncClient.post 是一个 async def 方法,调用它会返回一个可等待(awaitable)的协程。patch 或 MagicMock 没有自动推断对象的异步特性时,它只是同步地返回了 return_value。当事件循环试图 await 这个同步的 MagicMock 对象时,就会报错。patch 参数里显式使用 new=AsyncMock(return_value=...) 或 new_callable=AsyncMock。❌ 错误写法:
from unittest.mock import patch, MagicMock
mock_response = MagicMock(status_code=200)
# 当被 await 时会触发 TypeError!
with patch.object(httpx.AsyncClient, 'post', return_value=mock_response):
await my_crawler.fetch()✅ 正确写法:
from unittest.mock import patch, MagicMock, AsyncMock
mock_response = MagicMock(status_code=200) # Response 对象本身及其方法通常是同步的
# 正确!覆盖掉原来的方法,使其行为成为一个 AsyncMock
with patch.object(httpx.AsyncClient, 'post', new=AsyncMock(return_value=mock_response)):
await my_crawler.fetch()使用 side_effect 模拟循序多次请求:
with patch.object(httpx.AsyncClient, 'get', new=AsyncMock(side_effect=[mock_1, mock_2])):
...async def 的 Mock,必须保证它被调用时能走协程语境。httpx.AsyncClient.get 是异步的(需 AsyncMock),但它返回的 Response 对象上的 .json() 是同步的(需 MagicMock 即可)。c6f1797
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.