Dock nested properties with mock

I have a function call that returns an object:

r = Foo(x,y) 

where r has a rich set of nested properties. For example, I can access r.prop_a.prop_b.prop_c . I would like to make fun of Foo so that the specific property of sheet r changes, i.e. Such that r.prop_a.prop_b.prop_c returns a value under my control:

 >> r = Foo(x,y) >> r.prop_a.prop_b.prop_c 'fish' >> # some mock magic patching of Foo is taking place here >> r = Foo(x,y) >> r.prop_a.prop_b.prop_c 'my_fish' 

I am not interested in intermediate properties.

Is there an elegant way to trick attached properties with mock ?

+6
source share
2 answers

Replace the call to the mock object attribute as you expected:

 >> r1 = r_original(x, y) >> r1.prop_a.prop_b.prop_c 'fish' >> returner = mock.MagicMock() >> returner.prop_a.prop_b.prop_c = 'fish' >> r_mocked = mock.MagicMock(spec_set=r_original, return_value=returner) >> r2 = r_mocked(x, y) >> r2.prop_a.prop_b MagicMock name='returner.prop_a.prop_b' id='87412560'> >> r2.prop_a.prop_b.prop_c 'fish' 

This allows you to completely make fun of when determining a specific value.

+10
source

If you want to open the original properties elsewhere, you can define a wrapper class:

 class OverrideAttributePath(object): """A proxy class where we override a specific attribute path with the value given. For any other attribute path, we just return attributes on the wrapped object. """ def __init__(self, thing, path, value): self._thing = thing self._path = path self._value = value def __dir__(self): return dir(self._thing) def __len__(self): return len(self._thing) def __getitem__(self, index): if self._path == [index]: return self._value elif self._path[0] == index: return OverrideAttributePath( self._thing[index], self._path[1:], self._value) else: return self._thing[index] def __getattr__(self, key): if self._path == [key]: return self._value elif self._path[0] == key: return OverrideAttributePath( getattr(self._thing, key), self._path[1:], self._value) else: return getattr(self._thing, key) 

The following is used:

 >>> r = Foo(x,y) >>> r2 = OverrideAttributePath(r, ['prop_a', 'prop_b', 'prop_c'], 'my_fish') >>> r2.prop_a.prop_b.prop_c 'my_fish' 
+3
source

Source: https://habr.com/ru/post/922994/


All Articles