2016-05-18 3 views
2

から輸入されている場所、私はユニットテストを実行すると言う、重い外界関数を呼び出すトリガーしないことを確認する必要があり、この1:Pythonの:モックパッチモジュールそれは

# bigbad.py 
def request(param): 
    return 'I searched the whole Internet for "{}"'.format(param) 

複数のモジュールは、これを使用します関数(bigbad.request)を呼び出すと、別の方法でインポートされます(実際には、外部ライブラリからインポートすることもできます)。 bは、両方の機能を使用するに依存して二つのモジュール、a、bは、そこにある、と言う:

# a.py, from...import 
from bigbad import request 

def routine_a(): 
    return request('a') 

# b.py, imports directly 
import a 
import bigbad 

def routine_b(): 
    resp_a = a.routine_a() 
    return 'resp_a: {}, resp_b=request(resp_a): {}'.format(resp_a, bigbad.request(resp_a)) 

がbigbad.requestがこれまで呼び出されないことを確認する方法はありますか?このコードは、輸入品の一つだけを皮肉っ:

# test_b.py 
import unittest 
from unittest import mock 
import b 

with mock.patch('bigbad.request') as mock_request: 
    mock_request.return_value = 'mocked' 
    print(b.routine_b()) 

もちろん、私はBをリファクタリングし、輸入が、私は将来の開発中に誰かがこの規定を破るつもりはないことを保証することはできません。この方法を変更することができます。テストは実装の詳細よりも動作をテストすべきだと私は考えている。

答えて

0
import bigbad 
bigbad.request = # some dummy function 

これは限りfrom bigbad import requestを行う任意のモジュールをインポート/実行される前に、実行されるように動作します。つまり、後に実行される限り、ダミー関数を受け取ることになります。元requestが呼び出されることはありません、あなたは参照がインポートされるすべての場所にパッチを適用する必要がありますことを確認するために

1
# a.py, from...import 
from bigbad import request 

import mock 
with mock.patch('a.request', return_value='mocked') as mock_request: 
    ... 

これは面倒なので、可能であればは行いません。あなたのコードにfrom bigbad import requestがありますが、import bigbad; bigbad.requestを使用してください。

別の解決策:可能であれば、bigbad.pyを変更:

# bigbad.py 
def _request(param): 
    return 'I searched the whole Internet for "{}"'.format(param) 


def request(param): 
    return _request(param) 

はその後、いくつかのコードがfrom bigbad import requestない場合でも、あなたはwith mock.patch('bigbad._request', return_value='mocked') as mock_request:を行うことができると思います。

+0

補助機能を含むこの解決策は最も優雅に見えますが、実際には必ずしも可能ではありません。 –

関連する問題