Pytest类构造中的mock pandas read_excel



我正在使用Pytest进行一些集成测试。我正在阅读类构造函数输入的excel表。我不知道如何嘲笑panda的read_excel函数。我的实际代码,

import pandas as pd
class Sample:
def __init__(self, input_file_path):
self.df_input = pd.read_excel(
input_file_path, sheet_name="Input sheet", header=[0]
)

def calculation(self):
pass
def choose_template(self):
pass

sample_obj = Sample('./test.xlsx')
sample_obj.choose_template()

test_one.py,

@mock.patch.dict(os.environ, {"DB_CONNECTION_STRING": "Mock_Connection_String", 
"DB_DATABASE": "Mock_Db", 
"AZURE_STORAGE_CONNECTION_STRING": "Mock_Azure_connection_String", 
},clear=True)

def test_choose_template_valid():
expected = "fizz"
sample_obj = Sample('./test.xlsx')
sample_obj.choose_template()
actual = "fizz"
assert actual == expected

我得到以下错误。我理解为什么会发生这种事。但我需要一个关于如何模拟pd.read_excel调用的解决方案。

=============================================================== short test summary info ================================================================
FAILED test_report.py::test_choose_template_valid - FileNotFoundError: [Errno 2] No such file or directory: './test.xlsx'
================================================================== 1 failed in 0.96s ===================================================================

您的主要问题是在导入模块时已经执行了代码。在这种情况下,您不能在调用它之前对其进行模拟。

在通常的if __name__ == "__main__"检查之后调用该代码,或者更好的是,进入一个函数,并在检查之后调用那个函数:

class Sample:
...
def choose_sample_template(file_name):
sample_obj = Sample(file_name)
return sample_obj.choose_template()
if __name__ == "__main__":
choose_sample_template('./test.xlsx')

现在,您可以在测试pd.read_excel的功能时以通常的方式模拟它:

@mock.patch.dict(...)
@mock.patch("your_module.pd.read_excel")
def test_choose_template_valid(mocked_read):
mocked_read.return_value = ... # some df
expected = "fizz"   
actual = choose_sample_template('./test.xlsx')
assert actual == expected

其中CCD_ 4是定义CCD_ 5的模块。

如果您在测试的呼叫中有多个对pd.read_excel的后续呼叫,如注释中所述,您可以使用side_effect而不是return_value:

@mock.patch.dict(...)
@mock.patch("your_module.pd.read_excel")
def test_choose_template_valid(mocked_read):
mocked_read.side_effect = [
some_df,
second_df,
third_df
]
...

最新更新