我想设置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)
答案 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