web-dev-qa-db-ja.com

モックを使用して存在しない属性にパッチを適用する

__getattr__マジックを使用して、クラスに実際には存在しないいくつかの属性を解決するクラスを使用するコンテキストマネージャーをテストしようとしています。クラスにパッチを適用しようとすると、モックがAttributeErrorを発生させるという問題が発生しています。

パッチを適用するオブジェクトの簡略化された例。

class MyClass(object):
    def __getattr__(self, attr):
        if attr == 'myfunc':
            return lambda:return None
        raise AttributeError('error')


class MyContextManager(object):
    def __init__(self):
        super(MyContextManager, self).__init__()
        self.myclass = MyClass()

    def __enter__(self):
        pass

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.myclass.myfunc()

テストコード

def test_MyContextManager():
    with patch.object(MyClass, 'myfunc', return_value=None) as mock_obj:
        with MyContextManager():
             pass

    # Do some tests on mock object

これが私が得るエラーです:

AttributeError: <class 'MyClass'> does not have the attribute 'myfunc'

これを実行してテストを実行することはできますが、属性が自動的に復元されません(または、この場合は単にモック属性が削除されます)。

MyClass.myfunc= Mock(return_value=None)

これを実現するために、モック以外の別のライブラリを使用することもできます。私もpytestを使用しています。

17
Brendan Abel

これらの種類のテストで patch を使用するには、createパラメーターを使用する必要があります。このパラメーターは、存在しない場合は属性を強制的に作成します。

したがって、テストは次のようなことを行う必要があります。

def test_MyContextManager():
    with patch.object(MyClass, 'myfunc', create=True, return_value=None) as mock_obj:
        with MyContextManager():
             pass
25
Michele d'Amico