I have a program like this:
class SomeClass:
_attribute = None
def __init__(self, attribute):
self._attribute = attribute
@property
def attribute(self):
print("abc")
return self._attribute
class SomeChildClass:
context: SomeClass
def __init__(self):
pass
def print_attribute(self):
print(self.context.attribute)
I want to unittest the print_attribute method of SomeChildClass. Therefore I want to Mock both the SomeClass itself and the attribute property of this class.
When I use
def test_print_attribute(self):
with patch('app.some_class.SomeClass.attribute', new_callable=PropertyMock) as mock_attr:
mock_attr.return_value = "TEST"
some_class = SomeClass(attribute="abc")
self.child_class = SomeChildClass()
self.child_class.context = some_class
self.child_class.print_attribute()
it is working and i get TEST as output. The problem with this solution is that a real instance of SomeClass needs to be created. My ultimate goal would be something like this:
def test_print_attribute(self):
with patch('app.some_class.SomeClass.attribute', new_callable=PropertyMock) as mock_attr:
mock_attr.return_value = "TEST"
some_class = MagicMock()
self.child_class = SomeChildClass()
self.child_class.context = some_class
self.child_class.print_attribute()
Here I get only an object of MagicMock printed instead of TEST:
<MagicMock name='mock.attribute' id='2576201109456'>
I also tried this, which also returns a MagicMock object:
@patch('app.some_class.SomeClass')
def test_print_attribute(self, mock_some_class):
child_class = SomeChildClass()
child_class.context = mock_some_class
mock_some_class.attribute.return_value = "TEST"
child_class.print_attribute()
<MagicMock name='SomeClass.attribute' id='1701032644768'>
The solution was just to don't call the return_value method on the mock and access the attribute directly.
@patch('app.some_class.SomeClass')
def test_print_attribute(self, mock_class):
child_class = SomeChildClass()
child_class.context = mock_class
mock_class.attribute = "TEST"
child_class.print_attribute()
If anyone could explain this behavior I will accept the answer :)