问题描述
mymodule.py
def write_df_to_csv(self,df,modified_fn):
new_csv = self.path + "/" + modified_fn
df.to_csv(new_csv,sep=";",encoding='utf-8',index=False)
test_mymodule.py
class TestMyModule(unittest.TestCase):
def setUp(self):
args = parse_args(["-f","test1"])
self.mm = MyModule(args)
self.mm.path = "Random/path"
self.test_df = pd.DataFrame(
[
["bob","a"],["sue","b"],"c"],["joe",["bill","d"],["max",],columns=["A","B"],)
def test_write_df_to_csv(self):
to_csv_mock = mock.Magicmock()
with mock.patch("project.mymodule.to_csv",to_csv_mock,create=True):
self.mm.write_df_to_csv(self.test_df,"Stuff.csv")
to_csv_mock.assert_called_with(self.mm.path + "/" + "Stuff.csv")
当我运行这个测试时,我得到:
FileNotFoundError: [Errno 2] No such file or directory: 'Random/path/Stuff.csv'
我试图在我的方法中模拟 to_csv
。我的其他测试按预期运行,但是我不确定这个测试哪里出了问题。我对 Magicmock 的使用是正确的,还是我忽略了其他东西?
解决方法
您没有提供一个最小的、可重现的示例,所以我不得不去掉一些东西来完成这项工作。我想你可以自己填补缺失的部分。
一个问题是 mock.patch("project.mymodule.to_csv",...)
试图在导入路径 to_csv
处模拟 module 中名为 project.mymodule
的 class .这只是“有效”,因为您通过了 create=True
,但当然嘲笑以前不存在的东西是没有效果的,因为没有人会调用它。
您可以使用 DataFrame
模拟整个 mock.patch("pandas.DataFrame",...)
类。注意:无论您如何(甚至是否)在当前模块中导入 pd
,它都不是 pandas
。
但是随后您的单元测试将断言 to_csv
在 any DataFrame
上被调用,不一定是您传入的那个。通过模拟 just 我们传递给 to_csv
的一个 DataFrame
对象上的 write_df_to_csv
方法,测试变得更全面,也更容易理解。我们可以使用 mock.patch.object
来做到这一点。
mock.patch.object
返回模拟函数,我们随后可以在其上调用断言。因为它是一个方法模拟,而不是一个自由函数,所以我们不需要在断言中传递 self
参数。
project/mymodule.py
def write_df_to_csv(df,file_name):
df.to_csv(file_name,sep=";",encoding='utf-8',index=False)
project/test_mymodule.py
import unittest.mock as mock
import unittest
import pandas as pd
import project.mymodule as mm
class TestMyModule(unittest.TestCase):
def test_write_df_to_csv(self):
test_df = pd.DataFrame(...)
with mock.patch.object(test_df,"to_csv") as to_csv_mock:
mm.write_df_to_csv(test_df,"Stuff.csv")
to_csv_mock.assert_called_with("Stuff.csv")
if __name__ == '__main__':
unittest.main()
输出
测试现在以正确的方式失败了,因为参数实际上并不匹配!
$ python -m project.test_mymodule
F
======================================================================
FAIL: test_write_df_to_csv (__main__.TestMyModule)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/project/test_mymodule.py",line 25,in test_write_df_to_csv
to_csv_mock.assert_called_with("Stuff.csv")
File "/usr/lib/python3.8/unittest/mock.py",line 913,in assert_called_with
raise AssertionError(_error_message()) from cause
AssertionError: expected call not found.
Expected: to_csv('Stuff.csv')
Actual: to_csv('Stuff.csv',sep=';',index=False)
----------------------------------------------------------------------
Ran 1 test in 0.003s
FAILED (failures=1)
,
您必须以带正斜杠的 a 开头。这是更正后的代码:
self.mm.path = "/Random/path/"
也改变:
to_csv_mock.assert_called_with(self.mm.path + "Stuff.csv")
编辑:正如@Thomas 所说,我不确定 project.mymodule.to_csv
是否正确!