How to mock a readonly property with mock?

charlax picture charlax · Aug 6, 2012 · Viewed 59.8k times · Source

How do you mock a readonly property with mock?

I tried:

setattr(obj.__class__, 'property_to_be_mocked', mock.Mock())

but the issue is that it then applies to all instances of the class... which breaks my tests.

Do you have any other idea? I don't want to mock the full object, only this specific property.

Answer

jamescastlefield picture jamescastlefield · Aug 21, 2014

I think the better way is to mock the property as PropertyMock, rather than to mock the __get__ method directly.

It is stated in the documentation, search for unittest.mock.PropertyMock: A mock intended to be used as a property, or other descriptor, on a class. PropertyMock provides __get__ and __set__ methods so you can specify a return value when it is fetched.

Here is how:

class MyClass:
    @property
    def last_transaction(self):
        # an expensive and complicated DB query here
        pass

def test(unittest.TestCase):
    with mock.patch('MyClass.last_transaction', new_callable=PropertyMock) as mock_last_transaction:
        mock_last_transaction.return_value = Transaction()
        myclass = MyClass()
        print myclass.last_transaction
        mock_last_transaction.assert_called_once_with()