我想模拟 Pandas 函数
read_csv
,它在我的代码中由高阶函数动态返回,但 pytest patch
似乎并不允许这样做。
import pandas as pd
format_read_func_mapping = {"csv": pd.read_csv, "parquet": pd.read_parquet}
def my_func(s3_path, file_format):
read_func = format_read_func_mapping[file_format]
df = read_func(f"{s3_path}")
return df
当我运行单元测试时,我有以下内容
from unittest.mock import patch
@patch(f"{MODULE_PATH}.pd.read_csv")
def test_my_func(self, mock_read_csv):
mock_read_csv.side_effect = [my_test_data_frame]
my_func(dummy_s3_path, "csv")
我希望测试会使用模拟并返回我的测试数据,但事实并非如此,它实际上调用了
pandas.read_csv
来尝试从 dummy_s3_path
读取。
但是,如果我不从映射动态返回
pd.read_csv
,只需直接在pd.read_csv(f"{s3_path}")
中使用my_func
,模拟效果就很好。
这是 pytest 的限制吗?还是我嘲笑的方式不正确?
谢谢。
问题是您在模块级别定义
format_read_func_mapping
字典,因此当导入模块时,会使用键 'csv'
的值创建字典,作为对原始 pd.read_csv
的引用,这确实当您之后修补pd.read_csv
时,不会被修改。
要在模块的全局命名空间中修补
format_read_func_mapping
,您可以使用patch.dict
来修补字典的特定键:
import module
@patch.dict(module.format_read_func_mapping, {"csv": Mock(side_effect=[my_test_data_frame])})
def test_my_func():
my_func(dummy_s3_path, "csv")