pythonmockingpropertiesmox

How do I mock a class property with mox?


I have a class:

class MyClass(object):
    @property
    def myproperty(self):
        return 'hello'

Using mox and py.test, how do I mock out myproperty?

I've tried:

mock.StubOutWithMock(myclass, 'myproperty')
myclass.myproperty = 'goodbye'

and

mock.StubOutWithMock(myclass, 'myproperty')
myclass.myproperty.AndReturns('goodbye')

but both fail with AttributeError: can't set attribute.


Solution

  • When stubbing out class attributes mox uses setattr. Thus

    mock.StubOutWithMock(myinstance, 'myproperty')
    myinstance.myproperty = 'goodbye'
    

    is equivalent to

    # Save old attribute so it can be replaced during teardown
    saved = getattr(myinstance, 'myproperty')
    # Replace the existing attribute with a mock
    mocked = MockAnything()
    setattr(myinstance, 'myproperty', mocked)
    

    Note that because myproperty is a property getattr and setattr will be invoking the property's __get__ and __set__ methods, rather than actually "mocking out" the property itself.

    Thus to get your desired outcome you just go one step deeper and mock out the property on the instance's class.

    mock.StubOutWithMock(myinstance.__class__, 'myproperty')
    myinstance.myproperty = 'goodbye'
    

    Note that this might cause issues if you wish to concurrently mock multiple instances of MyClass with different myproperty values.