pytest中mocker.patch.object返回Mock与传入实例不一致问题
解决pytest-mock打补丁os.makedirs时side_effect不生效的问题
你之前的写法核心问题在于:手动创建了MagicMock并设置为patch的return_value,但mocker.patch/mocker.patch.object本身会自动生成一个Mock实例来替换原函数,你自己创建的Mock和这个替换用的实例完全是两个独立对象。修改自己创建的Mock的side_effect,根本不会影响被测代码调用的那个替换函数——因为被测代码调用的是patch生成的Mock,不是你自己创建的Mock的返回值。
正确的Fixture写法
不需要手动创建MagicMock,直接获取mocker.patch返回的Mock实例:
def mock_makedirs(mocker): # 补丁路径必须对应被测脚本中os.makedirs的实际使用位置 # 若被测脚本是import os后用os.makedirs,路径需写成 模块名.os.makedirs mock = mocker.patch("infrastructure.scripts.src.server_administrator.os.makedirs") return mock
测试用例调整
直接使用fixture返回的真实Mock实例设置side_effect:
def test_if_directory_exist_exception_is_not_raised(administrator, mock_makedirs): # 给patch生成的Mock设置异常副作用 mock_makedirs.side_effect = Exception("Directory already exists.") with pytest.raises(Exception) as exc_info: administrator.initialize_server() # 注意:Exception对象无法直接与字符串比较,需转为字符串后断言 assert str(exc_info.value) == "Directory already exists."
关键注意点
- 补丁路径要精准:遵循「where it's used」原则,补丁必须针对被测代码中实际调用
makedirs的那个引用。比如被测脚本是import os就补丁your_module.os.makedirs;是from os import makedirs就补丁your_module.makedirs。 - 不要手动创建Mock绑定return_value:patch的核心是替换原函数为它生成的Mock实例,你需要操作的就是这个实例——除非你要模拟的是函数的返回值,而非函数本身的行为。
内容的提问来源于stack exchange,提问作者Chris Schmitz
相关产品推荐
相关产品推荐

