2016-08-26 22 views
3

モックを使用してコンテキストマネージャの機能にパッチを適用しようとしています。ここにはwithという文が入ったテストコードがあります。パッチは自分のコードの正しい場所で実行されます。コンテキストマネージャ用のモックがAttributeErrorで失敗しました:__exit__

@patch("__main__.opened_w_error") 
def test_get_recipe_file(self, mo): 
    mo.return_value = (Mock(), None) 
    mo.__enter__ = Mock(return_value=None) 
    mo.__exit__ = Mock(return_value=None) 
    with mo(…) as (fd, err): # AttributeError: __exit__ is raised here. 
     print(fd) 
     print(err) 

しかしwith mo(…) as (fd, err)AttributeError: __exit__を発生させます。

documentation for mocking magic methods状態あなたは、コードの後半部分は、私はモックしようとしているものです

with mo as (fd, err): 
    … 

としてそれを使用する必要があります。 しかし、それは私のコードでどのように使用されていません。本当に興味のある方は、ファイルを開けたり、エラーをキャッチしたりするexample 6 opened_w_error() in PEP 343を盗もうとしています。したがってコードは次のとおりです。

with open_w_error(filename, 'r') as (fd, err): 
    … 

後者は私が模倣しようとしているものです。オブジェクトあなたが文でに渡す

+0

@TimFuchs:おっと、質問に編集します。ありがとうございました。 – Sardathrion

答えて

4

as構築物について使用__enter__からの戻り値で、__enter____exit__メソッドを持っていなければならないものです。あなたの場合、mo(...)を呼び出しています。これは(Mock(), None)を返します。これはコンテキストマネージャではありません。この戻り値を__enter__メソッドに移動する必要があります。

@patch("__main__.opened_w_error") 
def test_get_recipe_file(self, mo): 
    mo.__enter__ = Mock(return_value=(Mock(), None)) 
    mo.__exit__ = Mock(return_value=None) 
    with mo as (fd, err): 
     print(fd) 
     print(err) 

EDIT:あなたはまだmoを呼び出したい場合は、その戻り値コンテキストマネージャを作ります。

@patch("__main__.opened_w_error") 
def test_get_recipe_file(self, m_opened_w_error): 
    mo = Mock() 
    mo.__enter__ = Mock(return_value=(Mock(), None)) 
    mo.__exit__ = Mock(return_value=None) 
    m_opened_w_error.return_value = mo 
    with m_opened_w_error(...) as (fd, err): 
     print(fd) 
     print(err) 
1

あなたはそれが(tuple)戻っているオブジェクトがその上に__enter____exit__属性を持っていないmo(..)を呼び出しているときに問題があります。

momoreturn_valueに割り当てて、設定しているコンテキストマネージャの属性が見つかるようにします。あなたが必要なもの

@patch("__main__.opened_w_error") 
def test_get_recipe_file(self, mo): 
    mo.return_value = mo 
    mo.__enter__ = Mock(return_value=(Mock(), None)) 
    mo.__exit__ = Mock(return_value=None) 
    with mo('file', 'r') as (fd, err): 
     print(fd) 
     print(err) 
     mo.assert_called_once_with('file', 'r') # Should be True 
0

はこれです:

with mock.patch('__main__.opened_w_error') as mo: 
    mo.__enter__ = Mock(return_value=(Mock(), None)) 
    mo.__exit__ = Mock(return_value=None) 
    # Your code goes here 
関連する問題