Skip to content
Advertisement

Mock property method on class

I have the following dataclass:

from dataclasses import dataclass

@dataclass
class Foo:
    bar: str
    baz: str

    @property
    def qux(self) -> str:
        return self.bar

I’d like to change the behavior of qux during testing. I’m aware of PropertyMock, and could write something like:

with mock.patch("__main__.Foo.qux", new_callable=mock.PropertyMock(return_value="test")):
    foo = Foo(bar="a", baz="b")
    print(foo.qux)

I’d instead like to substitute the property method (undecorated), something like:

def _unbound(self) -> str:
    return self.baz

with mock.patch("__main__.Foo.qux", new_callable=mock.PropertyMock(new=_unbound)):
    foo = Foo(bar="a", baz="b")
    print(foo.qux)

I’ve tried various combinations of new_callable, new, etc. when creating the patch object, but I’m seeing:

TypeError: _unbound() missing 1 required positional argument: 'self'

Is there a way I can mock out a property with a bound method containing a reference to the dataclass?

Advertisement

Answer

You can write your own property mock, that does what you want in __get__:

class MyMock(mock.PropertyMock):
    def __get__(self, obj, obj_type=None):
        return _unbound(obj)


def test_unbound():
    with mock.patch("__main__.Foo.qux", new=MyMock()):
        foo = Foo(bar="a", baz="b")
        assert foo.qux == "b"

The problem is to get the correct object to _unbound.
There must be a cleaner way to achieve this, though I don’t see it…

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement