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…