如何Mock Python的subprocess.check_output多不同调用?报错排查
问题分析与解决
你遇到的错误根源是误解了new_callable的作用:它的参数需要是一个创建Mock对象的工厂函数(比如MagicMock),而不是直接作为被替换的函数使用。你的代码中,当mocker.patch调用my_outputs时没有传入任何参数,导致args为空,函数返回None,最终subprocess.check_output被替换成了None,调用自然会抛出NoneType不可调用的错误。
正确实现方式
要根据传入参数动态返回不同结果,应该使用Mock对象的side_effect属性——它可以绑定一个函数,每次Mock被调用时都会执行这个函数,并返回对应结果。
修正后的代码
@pytest.fixture def mock_check_output(mocker): def dynamic_return(*args, **kwargs): # 提取调用时传入的命令列表 cmd = args[0] if cmd[0] == "readelf": # 注意:check_output返回字节流,需和真实返回类型一致 return b"fake_readelf_content\n.interp: /lib/ld-linux.so.2" elif cmd[0] == "ldd": return b"fake_ldd_output" else: return b"fake_firmware_paths" # 先patch掉check_output,得到Mock对象 mock = mocker.patch("subprocess.check_output") # 给Mock绑定动态返回逻辑 mock.side_effect = dynamic_return return mock def test_qemu_overlay(tuxrun_args_qemu_overlay, lava_run, mock_check_output): main() # 可选:验证check_output是否按预期被调用 mock_check_output.assert_called_with(["readelf", "-p", ".interp", "qemu_binary"])
关键说明
side_effect的作用:它接受一个函数,该函数会接收Mock被调用时的所有参数,你可以根据这些参数判断应该返回什么模拟数据。- 返回类型匹配:真实的
subprocess.check_output返回字节串(bytes),所以你的模拟返回值也必须是字节串,否则后续的.decode("utf-8")会报错。 - Mock验证:测试中可以通过
assert_called_with或assert_called_once等方法,验证check_output是否被正确调用,确保你的业务逻辑符合预期。
内容的提问来源于stack exchange,提问作者stsquad
相关产品推荐
相关产品推荐

