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 existsos.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?
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.
In your test the only problem was the instruction:
mock_os.makedirs.raiseError.side_effect = OSError()
So an other solution for your test is:
try-except OSError
in your production code@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')