使用pytest_mock Mock跨类调用的类方法时,如何确定正确的mocker.patch路径?
嘿,我来帮你搞定这个问题!你遇到的AssertionError: assert None其实有两个关键问题需要排查——一个是容易忽略的断言写法失误,另一个是Mock路径的正确性确认,咱们一步步来:
1. 先修正断言写法(这是assert None报错的直接原因)
你在测试里写了这样的代码:
assert mock_object.assert_called_once()
但assert_called_once()本身是无返回值的断言方法——它会在目标方法未被调用时主动抛出AssertionError,完全不需要再用assert包裹它。你现在的写法相当于断言None为真,这必然会触发AssertionError: assert None的错误。
把这行改成:
mock_object.assert_called_once()
就可以解决这个报错了。如果需要验证调用参数,还可以用更精确的断言:
mock_object.assert_called_once_with('1231231')
2. 确认Mock路径的正确性(核心逻辑)
Python的Mock机制是基于模块中实际引用的对象,而不是对象的原始定义位置。在你的api/dog/handlers/internal.py中,你是直接从api.dog.helpers.visits导入VisitOrchestrator的,所以在internal.py模块里,VisitOrchestrator是一个本地导入的引用。
你之前尝试的api.dog.handlers.internal.VisitOrchestrator.fetch_visit其实是正确的Mock路径,只是因为断言写法的错误,让你误以为路径不对。为了确保万无一失,再检查两个点:
- 确认测试文件中导入的
InternalDogWebhookResource确实来自api.dog.handlers.internal模块 - 确认
internal.py中的导入语句是from api.dog.helpers.visits import VisitOrchestrator(你给出的代码是正确的)
修正后的完整测试代码
另外还要注意:你原来的请求JSON{'blag': 'blargh'}不符合接口的触发条件——接口需要判断event_type == EventType.CHANGE并读取event['visitId'],所以请求参数需要补充对应的字段,否则fetch_visit不会被调用。修正后的完整测试代码如下:
import pytest from pytest_mock import MockerFixture from api.dog.handlers.internal import InternalDogWebhookResource, EventType from tests.v0.utils import url_for def test_webhook_valid(client, config, mocker: MockerFixture): visit_id = '1231231' # 正确的Mock路径 mock_fetch_visit = mocker.patch( 'api.dog.handlers.internal.VisitOrchestrator.fetch_visit', return_value=visit_id, ) res = client.post( url_for(InternalDogWebhookResource), json={'event_type': 'CHANGE', 'visitId': visit_id} # 补充触发逻辑所需的字段 ) # 直接调用断言方法,无需额外assert mock_fetch_visit.assert_called_once_with(visit_id) # 同时断言响应状态码符合预期 assert res.status_code == 204
内容的提问来源于stack exchange,提问作者metersk

