12

オブジェクトを返す関数呼び出しがあります。

r = Foo(x,y)

ここにrは、ネストされたプロパティの豊富なセットがあります。たとえば、にアクセスできますr.prop_a.prop_b.prop_cFooの特定の葉のプロパティrが変更されるように、つまりr.prop_a.prop_b.prop_c、私の制御下で値を返すように、モックを作成したいと思います。

>> 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'

中間特性はあまり気にしません。

ネストされたプロパティをモックでモックするエレガントな方法はありますか?

4

2 に答える 2

24

モック オブジェクトの属性呼び出しを期待どおりに置き換えます。

>> 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'

これにより、特定の値を定義しながらモックを最大限に活用できます。

于 2012-12-16T00:09:11.607 に答える
2

元のプロパティを別の場所で公開したい場合は、ラッパー クラスを定義できます。

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)

使用方法は次のとおりです。

>>> r = Foo(x,y)
>>> r2 = OverrideAttributePath(r, ['prop_a', 'prop_b', 'prop_c'], 'my_fish')
>>> r2.prop_a.prop_b.prop_c
'my_fish'
于 2015-12-10T15:52:42.923 に答える