Python 如何模拟由高阶函数返回的函数

问题描述 投票:0回答:1

我想模拟 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 的限制吗?还是我嘲笑的方式不正确?

谢谢。

python pytest python-unittest
1个回答
0
投票

问题是您在模块级别定义

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")
© www.soinside.com 2019 - 2024. All rights reserved.