使用Pytest测试异步方法时,被补丁方法的调用次数未正确统计
问题分析与解决方案
你的问题核心是:mock对象的call_count未正确更新,但实际代码中确实调用了get_item方法,且模拟返回值生效。这几乎可以确定是mock路径不匹配导致的——你patch的对象与中间件实际使用的table不是同一个引用。
关键原因
假设你的CacheMiddleware代码中是这样导入table的:
# api/utils/cache_middleware.py from api.utils.dynamo import table class CacheMiddleware: async def dispatch(self, request, call_next): # 使用 table.get_item(...)
此时,cache_middleware模块会在导入时创建一个对dynamo.table的本地引用。而你当前fixture中patch的是api.utils.cache_middleware.dynamo.table——这仅修改了dynamo模块里的table,但cache_middleware模块里的本地引用还是原来的table对象,所以中间件实际调用的是未被mock的原始对象,你断言的却是新mock的对象,自然call_count为0。
解决方案
修改fixture中的patch路径,直接patchcache_middleware模块里的本地table引用:
@pytest.fixture(scope="function", name="cache_service_table_get_mock") def fixture_cache_service_table_get_mock(mocker: MockerFixture): # 改为patch中间件模块内的table引用 mock_table = mocker.patch("api.utils.cache_middleware.table") mock_table.get_item.return_value = {"Items": []} mock_table.put_item.return_value = None yield mock_table
验证方法
可以在测试函数中添加打印,确认mock对象与中间件使用的对象是否为同一个:
@pytest.mark.asyncio async def test_cache_no_hit(cache_service_table_get_mock: MagicMock): from api.utils.cache_middleware import table as middleware_table # 打印两个对象的内存地址,若相同则路径正确 print(f"Mock table ID: {id(cache_service_table_get_mock)}") print(f"Middleware table ID: {id(middleware_table)}") # 原有测试代码...
额外注意点
如果get_item是异步方法,建议用AsyncMock替代MagicMock,确保mock返回可等待对象:
from unittest.mock import AsyncMock @pytest.fixture(scope="function", name="cache_service_table_get_mock") def fixture_cache_service_table_get_mock(mocker: MockerFixture): mock_table = mocker.patch("api.utils.cache_middleware.table", new_callable=AsyncMock) mock_table.get_item.return_value = {"Items": []} mock_table.put_item.return_value = None yield mock_table
内容的提问来源于stack exchange,提问作者Jesus Diaz Rivero
相关产品推荐
相关产品推荐

