Python MagicMock到os.listdir不会引发错误

时间:2016-09-22 06:53:41

标签: python unit-testing mocking

我想设置os.listdir以在UT中引发OSError,但它不会引发任何事情。

我的代码:

def get_list_of_files(path):
    try:
        list_of_files = sorted([filename for filename in
                                os.listdir(path) if
                                filename.startswith('FILE')])

    except OSError as error:
    raise Exception(error)

    return list_of_files

def setUp(self):
    self.listdir_patcher = patch('os.listdir')
    self.mock_listdir = self.listdir_patcher.start()
    self.mock_listdir_rv = MagicMock()
    self.mock_listdir.return_value = self.mock_listdir_rv

def tearDown(self):
    self.listdir_patcher.stop()
def test(self):
    e = OSError('abc')
    self.mock_listdir_rv.side_effect = e
    with self.assertRaises(OSError):
         get_list_of_files('path')

有什么问题? (我不能使用普通的Mock到os.listdir)

1 个答案:

答案 0 :(得分:1)

您需要为self.mock_listdir设置副作用,而不是它的返回值:

def test(self):
    e = OSError('abc')
    self.mock_listdir.side_effect = e
    with self.assertRaises(OSError):
         get_list_of_files('path')

毕竟,您希望调用os.listdir()来引发异常,而不是调用返回值os.listdir()(您从不使用os.listdir()())。

演示(使用patch()作为上下文管理器,与使用它作为装饰器具有相同的效果):

>>> from unittest.mock import patch
>>> import os
>>> with patch('os.listdir') as mock_listdir:
...     mock_listdir.side_effect = OSError('abc')
...     os.listdir('path')
...
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
  File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/mock.py", line 930, in __call__
    return _mock_self._mock_call(*args, **kwargs)
  File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/mock.py", line 986, in _mock_call
    raise effect
OSError: abc

请注意,设置side_effect模拟的self.mock_listdir将持续到其他测试!你应该真正使用新的补丁每次测试。您可以在每个测试中使用patch作为装饰器,使用它而不是使用每个测试用例的修补程序:

@patch('os.listdir')
def test(self, mock_listdir):
    e = OSError('abc')
    mock_listdir.side_effect = e
    with self.assertRaises(OSError):
         get_list_of_files('path')

如果您坚持使用修补程序,请从setUp开始,之后必须清除副作用(将其设置为None)。

除此之外,没有必要为MagicMock明确创建return_value个实例;这是默认的返回值。您可以改为存储默认值:

self.mock_listdir = self.listdir_patcher.start()
self.mock_listdir_rv = self.mock_listdir.return_value