我有一个带有方法的类,如果param被传递为true,则使用shutil.rmtree删除一些文件,如何模拟这种行为,以便其他测试不会破坏哪些需要这些文件。
我的班级看起来像这样 -
class FileConverter(object):
def __init__(self, path_to_files):
self._path_to_files = path_to_files
def convert_files(self, rmv_src=False):
doStuff()
if rmv_src:
shutil.rmtree(self.__path_to_files)
def doStuff():
# does some stuff
现在我的测试看起来像 -
class TestFileConverter(unittest.TestCase):
def test_convert_success(self):
input_dir = 'resources/files'
file_converter = FileConverter(input_dir)
file_converter.convert_files()
# assert the things from doStuff
@mock.patch('shutil.rmtree')
def test_convert_with_rmv(self, rm_mock):
input_dir = 'resources/files'
file_converter = FileConverter(input_dir)
file_converter.convert_files(True)
self.assertEquals(rm_mock, [call(input_dir)])
现在,当我运行此测试套件时,使用rmv进行测试会给出断言错误
<MagicMock name='rmtree' id='139676276822984'> != [call('resources/images')]
并且第一个测试给我发现文件未找到错误,因为模拟不起作用并且rmv源测试删除了文件
FileNotFoundError: [Errno 2] No such file or directory: 'resources/images'
如果我用rmv_source注释掉第二个测试,那么我的第一个测试工作正常。 我在这里做错了什么?
答案 0 :(得分:2)
您的模块已导入shutil.rmtree
,因此稍后在测试套件中进行模拟不会做任何事情。
您需要在导入FileConverter
时模拟模块,而不是之后。
import sys
from mock import MagicMock
sys.modules['shutil'] = MagicMock()
# and/or
sys.modules['shutil.rmtree'] = MagicMock()
import FileConverter
如果你仍然需要在测试代码中使用shutil,那么首先使用别名导入它,并在需要“真实”时使用它。模块:
import sys
from mock import MagicMock
import shutil as shutil_orig
sys.modules['shutil'] = MagicMock()
import shutil
print(type(shutil_orig.rmtree))
# <class 'function'>
print(type(shutil.rmtree))
# <class 'mock.mock.MagicMock'>
答案 1 :(得分:0)
除了call(input_dir)
对我不起作用外,原帖应该有用
@mock.patch('shutil.rmtree')
def test_convert_with_rmv(self, rm_mock):
input_dir = 'resources/files'
rm_mock.return_value = 'REMOVED'
file_converter = FileConverter(input_dir)
file_converter.convert_files(True)
rm_mock.assert_called_with(input_dir)
self.assertEqual(rm_mock.return_value, 'REMOVED')
test_convert_with_rmv
无法删除input_dir
,它可能从未创建过。您可以在调用convert_files
之前和之后的每个测试中声明此语句:
self.asserTrue(os.path.isdir(input_dir))