Python MagicMock to os.listdir not raise error
<p>I would like to set os.listdir to raise OSError in UT but it not raise anything.</p>

<p>My code:</p>

<pre><code>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')
</code></pre>

<p>What is the problem?
(I can not use normal Mock to os.listdir) </p>

<p>You need to set the side effect for <code>self.mock_listdir</code>, not it's return value:</p>

<pre><code>def test(self):
    e = OSError('abc')
    self.mock_listdir.side_effect = e
    with self.assertRaises(OSError):
         get_list_of_files('path')
</code></pre>

<p>After all, you want the call to <code>os.listdir()</code> to raise the exception, not the call to the return value of <code>os.listdir()</code> (you never use <code>os.listdir()()</code>).</p>

<p>Demo (using <code>patch()</code> as a context manager, which has the same effects as using it as a decorator):</p>

<pre><code>&gt;&gt;&gt; from unittest.mock import patch
&gt;&gt;&gt; import os
&gt;&gt;&gt; with patch('os.listdir') as mock_listdir:
...     mock_listdir.side_effect = OSError('abc')
...     os.listdir('path')
...
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 3, in &lt;module&gt;
  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
</code></pre>

<p>Note that setting the <code>side_effect</code> of the <code>self.mock_listdir</code> mock will persist to other tests! You should really use a new patch <em>per test</em>. You can use <code>patch</code> as a decorator on each test, use this instead of using a per-testcase patcher:</p>

<pre><code>@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')
</code></pre>

<p>If you do stick to using a patcher you start in the <code>setUp</code>, you'd have to clear the side effect afterwards (set it to <code>None</code>).</p>

<p>Aside from all that, there is no need to explicitly create the <code>MagicMock</code> instance for a <code>return_value</code>; that's the default return value already. You could instead store that default:</p>

<pre><code>self.mock_listdir = self.listdir_patcher.start()
self.mock_listdir_rv = self.mock_listdir.return_value
</code></pre>

python mocking