简体   繁体   中英

How can I make mock.mock_open raise an IOError?

I need to test a instance method that calls open . In the first test case, I set mock.mock_open to return a string, as expected. This works wonderfully.

However, I also need to test the case in which an IOError is thrown from this function. How can I make mock.mock_open raise an arbitrary exception?

This is my approach so far:

@mock.patch.object(somemodule, 'generateDefaultKey')
def test_load_privatekey(self, genkey)
    mo = mock.mock_open(read_data=self.key)
    mo.side_effect = IOError
    with mock.patch('__main__.open', mo, create=True):
        self.controller.loadPrivkey()

    self.assertTrue(genkey.called, 'Key failed to regenerate')

Assign the exception to mock.mock_open.side_effect :

mock.mock_open.side_effect = IOError

From the mock.Mock.side_effect documentation :

This can either be a function to be called when the mock is called, or an exception (class or instance) to be raised.

Demo:

>>> mock = MagicMock()
>>> mock.mock_open.side_effect = IOError()
>>> mock.mock_open()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mj/Development/venvs/stackoverflow-2.7/lib/python2.7/site-packages/mock.py", line 955, in __call__
    return _mock_self._mock_call(*args, **kwargs)
  File "/Users/mj/Development/venvs/stackoverflow-2.7/lib/python2.7/site-packages/mock.py", line 1010, in _mock_call
    raise effect
IOError

When using patch() as a context manager, a new mock object is produced; assign to that mock object:

with mock.patch('__main__.open', mo, create=True) as mocked_open:
    mocked_open.side_effect = IOError()
    self.controller.loadPrivkey()

I found Martijn's answer a little hard to generalize, so here is what I hope is a simpler answer less tied to the OPs initial code:

from unittest.mock import patch, mock_open


def func_to_test():
    try:
        with open('path/to/open', 'r') as file:
            return 1

    except IOError:
        return 2


def test_open_error():
    with patch("builtins.open", mock_open()) as mock_file:
        mock_file.side_effect = IOError()

        assert func_to_test() == 2

        mock_file.assert_called_with('path/to/open', 'r')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM