Python模拟不适用于shutil.rmtree

时间:2018-03-20 07:24:45

标签: python unit-testing testing mocking

我有一个带有方法的类,如果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注释掉第二个测试,那么我的第一个测试工作正常。 我在这里做错了什么?

2 个答案:

答案 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))