How can I raise exceptions while accessing an attribute of the mocked object?
I have tried to do the same with the following snippet,
import unittest
from unittest import TestCase
from django.core.exceptions import ObjectDoesNotExist
from unittest.mock import MagicMock, PropertyMock
def function_to_call_one_to_one(model_instance):
try:
return model_instance.artist.name
except ObjectDoesNotExist:
# calling `model_instance.artist` will raise `ObjectDoesNotExist` exception
return "raised `ObjectDoesNotExist`"
class TestObjectDoesNotExist(TestCase):
def test_artist_name(self):
model_instance = MagicMock()
model_instance.artist.name = "Michael Jackson"
name = function_to_call_one_to_one(model_instance)
self.assertEqual(name, "Michael Jackson")
def test_artist_name_with_error(self):
model_instance = MagicMock()
model_instance.artist = PropertyMock(side_effect=ObjectDoesNotExist)
res = function_to_call_one_to_one(model_instance)
self.assertEqual(res, "raised `ObjectDoesNotExist`")
if __name__ == '__main__':
unittest.main()
Unfortunately, the test function, test_artist_name_with_error(...)
has failed with message,
AssertionError: <MagicMock name='mock.artist.name' id='140084482479440'> != 'raised
ObjectDoesNotExist
'
How can I write the unit-test for this case?
Note: I have seen this SO post, Python: Mock side_effect on object attribute, but, it doesn't work for me. I hope, this example is a reproducible one.
Great question. Here's one part of the docs that you might have overlooked:
Because of the way mock attributes are stored you can’t directly attach a
PropertyMock
to a mock object. Instead, you can attach it to the mock type object.
This works:
type(model_instance).artist = PropertyMock(side_effect=ObjectDoesNotExist)