【问题标题】:Mock patches don't work more than once模拟补丁不工作不止一次
【发布时间】:2014-08-13 14:13:24
【问题描述】:

我无法让 mock 的补丁正常工作。在下面的代码中,只有test_base 中的第一个assertEqual 成功。如果我将第一个与第二个交换,同样只有第一个成功。

import os
import mock

def fake_isfile(filename):
    if filename == 'file.py':
        return True
    return False


def fake_walk():
    yield '.', ['tests', 'sub', '.hid'], ['tox.ini', 'amod.py', 'test_all.py']
    yield './tests', [], ['test_amod.py', 'run.py', '.hid.py']
    yield './sub', [], ['amod.py', 'bmod.py']


class TestIterFilenames(unittest.TestCase):

    def setUp(self):
        self.iter_files = lambda *a, **kw: list(tools.iter_filenames(*a, **kw))

    def test_stdin(self):
        self.assertEqual(self.iter_files(['-']), ['-'])

    @mock.patch('tools.os.path')
    @mock.patch('tools.os')
    def test_all(self, os_mod, os_path_mod):
        os_path_mod.normpath = os.path.normpath
        os_path_mod.basename = os.path.basename
        os_path_mod.join = os.path.join
        os_path_mod.isfile.side_effect = fake_isfile
        os_mod.walk.return_value = fake_walk()

        self.assertEqual(self.iter_files(['file.py', 'random/path']),
                         ['file.py', 'amod.py', 'test_all.py',
                          'tests/test_amod.py', 'tests/run.py', 'sub/amod.py',
                          'sub/bmod.py'])

        self.assertEqual(self.iter_files(['file.py', 'random/path'],
                                         'test_.*'),
                         ['file.py', 'amod.py', 'tests/test_amod.py',
                          'tests/run.py', 'sub/amod.py', 'sub/bmod.py'])

我查看了文档,发现要在每个测试方法之后进行清理,我必须执行以下操作:

import os
import mock

def fake_isfile(filename):
    if filename == 'file.py':
        return True
    return False


def fake_walk():
    yield '.', ['tests', 'sub', '.hid'], ['tox.ini', 'amod.py', 'test_all.py']
    yield './tests', [], ['test_amod.py', 'run.py', '.hid.py']
    yield './sub', [], ['amod.py', 'bmod.py']


class TestIterFilenames(unittest.TestCase):

    def setUp(self):
        self.iter_files = lambda *a, **kw: list(tools.iter_filenames(*a, **kw))

        self.patcher1 = mock.patch('radon.cli.tools.os.path')
        self.patcher2 = mock.patch('radon.cli.tools.os')

        os_path_mod = self.patcher1.start()
        os_mod = self.patcher2.start()
        os_path_mod.normpath = os.path.normpath
        os_path_mod.basename = os.path.basename
        os_path_mod.join = os.path.join
        os_path_mod.isfile.side_effect = fake_isfile
        os_mod.walk.return_value = fake_walk()

    def tearDown(self):
        self.patcher1.stop()
        self.patcher2.stop()

    def test_base(self):
        self.assertEqual(self.iter_files(['file.py', 'random/path']),
                         ['file.py', 'amod.py', 'test_all.py',
                          'tests/test_amod.py', 'tests/run.py', 'sub/amod.py',
                          'sub/bmod.py'])

    def test_exclude(self):
        self.assertEqual(self.iter_files(['file.py', 'random/path'],
                                         'test_.*'),
                         ['file.py', 'amod.py', 'tests/test_amod.py',
                          'tests/run.py', 'sub/amod.py', 'sub/bmod.py'])

但是,即使在这种情况下,第二个测试方法也会失败,因为 fake_walk 没有被调用(我确信这一点)。

【问题讨论】:

    标签: python unit-testing mocking


    【解决方案1】:

    您的fake_walk 是一个生成器,因此它只能迭代一次。将其用作side_effect,以便在每次调用os.walk() 时重新调用它:

    os_mod.walk.side_effect = fake_walk
    

    由于您实际上并未测试是否调用了os.walk(),因此您不妨将整个属性设置为函数:

    os_mod.walk = fake_walk
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-22
      • 2013-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多