I have a class that defines some properties with the @property decorator. When I patch that class and set autospec=True, i expect the property to behave as as it is spec'd
class MyClass(object):
def __init__(self):
self.will_not_be_mocked = 'not mocked'
@property
def will_be_mocked(self):
return 'mocked property'
Expected Behavior:
When I access the will_be_mocked property on an instance, it behaves like a string attribute.
>>> my_obj = MyClass()
>>> my_obj.will_be_mocked
'mocked property'
and it is not callable
>>> my_obj.will_be_mocked()
TypeError: 'str' object is not callable
So this test should pass:
with self.assertRaises(TypeError):
my_obj.will_be_mocked()
Observed Behavior:
When I patch the class, and set autospec=True, The property is included in the mock's spec as expected, however, it becomes a MagicMock, and is callable. So any code which tried to execute that property could pass the unittest and fail in production
@patch('__main__.MyClass', autospec=True)
def test_MyClass(self, MyClass):
my_obj = MyClass()
with self.assertRaises(TypeError):
my_obj.will_be_mocked()
AssertionError: TypeError not raised
Objective:
I want to define the class in such a way that it is easy to mock with autospec. This is why I'm trying to define properties instead of just adding attributes in __init__
.