pytest异常单元测试如何mock被测函数内部调用的函数
mock同模块函数的实现方法
直接用Python标准库自带的unittest.mock就能实现,不需要额外安装依赖;如果习惯用pytest生态的插件,也可以用pytest-mock简化写法。核心要注意patch路径的写法,这是绝大多数人mock不生效的原因。
核心规则
patch的路径必须写被测函数调用目标函数时的查找路径,简单说就是:check_name在哪个模块里调用create_list,就patch哪个模块下的create_list引用。
你的check_name和create_list都在src.sp_api.api.sp模块下,check_name直接调用同模块的create_list,所以patch路径必须是src.sp_api.api.sp.create_list,写错路径就会导致真实函数依然被执行。
标准库实现(无需额外装包)
修改test_sp.py的测试代码如下:
import pytest from unittest.mock import patch, Mock from src.sp_api.api.sp import check_name, NameExists def test_exception_existed_name(self): # 构造假返回数据 mock_apps = [] for app_name in ["p", "r", "g", "x"]: fake_app = Mock() fake_app.name = app_name mock_apps.append(fake_app) mock_resp = Mock() mock_resp.details = mock_apps # patch对应路径下的create_list,替换为mock对象 with patch("src.sp_api.api.sp.create_list") as mock_create_list: mock_create_list.return_value = mock_resp # 执行被测逻辑 with pytest.raises(NameExists): check_name(token="test_token", name="g") # 可选校验:确认create_list被正确调用 mock_create_list.assert_called_once_with("test_token")
- 如果你觉得用Mock对象不够直观,也可以自己写简单的类来模拟返回结构,效果完全一致:
class MockApp: def __init__(self, name): self.name = name class MockResponse: def __init__(self, details): self.details = details # 构造数据时换成自定义类即可 mock_apps = [MockApp(name=n) for n in ["p", "r", "g", "x"]] mock_resp = MockResponse(details=mock_apps)
pytest-mock简化写法
如果你安装了pytest-mock插件,可以直接用mocker夹具,省去手动写上下文管理器的步骤:
import pytest from unittest.mock import Mock from src.sp_api.api.sp import check_name, NameExists def test_exception_existed_name(self, mocker): # 构造假数据逻辑和上面完全一致 mock_apps = [] for app_name in ["p", "r", "g", "x"]: fake_app = Mock() fake_app.name = app_name mock_apps.append(fake_app) mock_resp = Mock() mock_resp.details = mock_apps mock_create_list = mocker.patch( "src.sp_api.api.sp.create_list", return_value=mock_resp ) with pytest.raises(NameExists): check_name(token="test_token", name="g") mock_create_list.assert_called_once_with("test_token")
注意:如果运行测试时提示找不到
src模块,在tests目录下新建conftest.py,把项目根目录加入Python导入路径即可。
内容的提问来源于stack exchange,提问作者Duc Vu
相关产品推荐
相关产品推荐

