Python Mock: Raising Error for function of Mocked Class

457 Views Asked by At

I'm trying to test some code that create or changes directories and files based on some inputs. My issue is raising exceptions when a method of a mocked object is called. For example, say I have some code:

def create_if_not_exists(dest):
    dir = os.path.dirname(dest)
    if not dir:
        # create if it doesn't exist
        try:
           os.makedirs(os.path.dirname(dest))
        except OSError:
           pass # Nevermind what goes here, it's unimportant to the question

My unit test follows these ideas:

  • os.path.dirname() returns None means that the path not exists
  • os.makedirs() raises an OSError Exception
@patch('my.package.os')
def test_create_dir_if_not_exists(self, mock_os):
    # dirname return None means that the path not exists
    mock_os.path.dirname.return_value = None
    # by following instruction I want to raise an OSError Exception
    mock_os.makedirs.raiseError.side_effect = OSError()

    with self.assertRaises(OSError)
        create_if_not_exists('test')

This setup returns AssertionError: OSError not raised but my understanding is it should raise the error when the makedirs call is made in the actual (non-test) method. Is my understanding incorrect?

1

There are 1 best solutions below

5
On BEST ANSWER

Try with the following patch in the test file:

@patch('my.package.os.path.dirname')
@patch('my.package.os.makedirs')
def test_create_dir_if_not_exists(self, mock_os_makedirs, mock_os_path_dirname):
    mock_os_path_dirname.return_value = None
    # mock_os.makedirs.raiseError.side_effect = OSError() <--- REMOVE raiseError
    mock_os_makedirs.side_effect = OSError()

    with self.assertRaises(OSError)
        create_if_not_exists('test')

Furthermore your function create_if_not_exists() must not to catch the OSError exception; so your create_if_not_exists() function must be modified as followed:

import os

def create_if_not_exists(dest):
    dir = os.path.dirname(dest)
    if not dir:
        # create if it doesn't exist
        #try:
            os.makedirs(os.path.dirname(dest))
        #except OSError:
        #   pass # Nevermind what goes here, it's unimportant to the question

otherwise the test fails.

Also your test was good

In your test the only problem was the instruction:

mock_os.makedirs.raiseError.side_effect = OSError()

So an other solution for your test is:

  • remove the try-except OSError in your production code
  • change your test code as following:
@patch('my.package.os')
def test_create_dir_if_not_exists(self, mock_os):
    mock_os.path.dirname.return_value = None
    #mock_os.makedirs.raiseError.side_effect = OSError() <--- REMOVE raiseError
    mock_os.makedirs.side_effect = OSError()

    with self.assertRaises(OSError):
        create_if_not_exists('test')