如何Mock子进程调用的Python脚本中的函数?
解决subprocess调用脚本时Mock函数无效的问题
你之前的Mock方法无效,核心原因是subprocess会启动独立的Python进程——测试代码里的Mock只作用于当前测试进程,新进程会重新加载目标脚本,完全不受之前的Mock配置影响。
下面给出两种可行的解决方案:
方案一:将脚本改为可导入模块(推荐)
把目标脚本改成可被导入的模块,直接调用里面的函数而非通过subprocess执行,这样就能正常使用unittest.mock来Mock目标函数。
修改目标脚本(some_python_script_file.py)
def some_function(): return "string_1" def main(): result = some_function() print(result) # 仅直接运行脚本时执行main逻辑 if __name__ == "__main__": main()
测试代码
from unittest import TestCase, mock import some_python_script_file class TestBlaBla(TestCase): @mock.patch('some_python_script_file.some_function') def test_lala(self, mock_some_func): # 设置Mock返回值 mock_some_func.return_value = "other_string" # 直接调用脚本的main函数 some_python_script_file.main() # 验证Mock被调用 mock_some_func.assert_called_once() # 捕获print输出并验证(需使用capsys fixture) captured = self.capsys.readouterr() self.assertEqual(captured.out.strip(), "other_string")
方案二:通过环境变量控制返回值(兼容subprocess场景)
如果必须保留subprocess调用的方式,可以在目标脚本中添加环境变量判断,让函数根据环境变量返回指定值。
修改目标脚本(some_python_script_file.py)
import os def some_function(): # 优先读取测试环境变量,不存在则用默认值 return os.getenv("TEST_SOME_FUNC_RETURN", "string_1") def main(): result = some_function() print(result) if __name__ == "__main__": main()
测试代码
from unittest import TestCase import subprocess import os class TestBlaBla(TestCase): def test_lala(self): # 复制当前环境变量并添加测试用变量 test_env = os.environ.copy() test_env["TEST_SOME_FUNC_RETURN"] = "other_string" # 调用脚本时传入修改后的环境变量 output = subprocess.check_output( ["python", "some_python_script_file.py"], env=test_env, text=True # 直接返回字符串而非字节 ) self.assertEqual(output.strip(), "other_string")
内容的提问来源于stack exchange,提问作者Petro Bzdanovich
相关产品推荐
相关产品推荐

