2012-09-21 11 views
16

私が使っているモッキングライブラリは... mockです。入れ子関数の模擬方法

私は関数(レガシーコード)のテストケースを記述しようとしたときに、この "擬似ネスト関数"問題に遭遇しました。

この関数は、他のモジュールとの依存度が非常に高い、非常に複雑な入れ子関数を使用しました。

mockでネストされた機能をモックすることができるのだろうかと思います。

答えて

2

ネストされた関数をモックオブジェクトに置き換えようとしていますか?そうであれば、関数がどれほど複雑であっても、それはかなり簡単です。あなたはほとんどすべてのpythonオブジェクトを置き換えるためにMagicMockを使うことができます。

何かを返す関数をシミュレートする必要がある場合は、MagicMockreturn_valueパラメータを設定することができます。あなたがどこかに内部のあなたのsuper_nested関数を呼び出すコードの別の部分をテストしようとすると、それをモックとしたいしている場合は、あなたがpatchを使用する必要があります

>>> super_nested_mock = mock.MagicMock() 
>>> super_nested_mock.return_value = 42 
>>> super_nested_mock() 
42 

:それはこのようになります。モックライブラリーでは、それはこのようなものになります。ここでは

with patch('super_nested') as super_nested_mock: 
    super_nested_mock.return_value = "A good value to test with" 
    assert my_function_that_calls_super_nested(5) == 20 

を、通常の代わりにsuper_nestedを呼ぶだろうwithブロックで何かがsuper_nested_mockを呼び出し、ちょうどあなたがそれに設定された値を返します。

パッチコールに正確に何を入れる必要があるかについて、いくつかの微妙な点があります。主に、テストしているモジュールが表示されるのでオブジェクトにパッチを当てたいとします。詳細は "where to patch"を参照してください。

+1

ネストされた関数はテストする関数にのみ存在するため、これは機能しません。だから、 'patch'はそれを直接見つけて置き換えることはできません。 – satoru

+0

私はあなたがテストしようとしていたことを誤解したと思います。私は後世のためにここに残すつもりです。しかし、幸運。 – Wilduck

5

1つのオプションは、オプションで関数呼び出しを許可するように関数を変更することです。あなたが持っている場合:へ

def fn_to_test(): 
    def inner_fn(): 
    return 1 
    return inner_fn() + 3 

変更を:

def fn_to_test(inner_fn = null) 
    def inner_fn_orig(): 
    return 1 
    if inner_fn==null: 
    inner_fn = inner_fn_orig 
    return fn() + 3 

次に「本当」の用途は右内機能を取得します、そして、あなたのテストで、あなた自身を提供することができます。

あなたもこれを行うことができ
fn_to_test() # calls the real inner function 
def my_inner_fn(): 
    return 3 
fn_to_test(inner_fn=my_inner_fn) # calls the new version 

:あなたはGoogleからのネストされた関数呼び出し(機能連鎖)を模擬する必要があります例えば

fn_to_test() # calls the real inner function 
def my_inner_fn(): 
    return 3 
fn_to_test.inner_fn = my_inner_fn 
fn_to_test() # calls the new version 
18

:あなただけのオーバーライドを定義

def fn_to_test(): 
    def inner_fn_orign(): 
    return 1 
    inner_fn = inner_fn_orig 
    try: 
    inner_fn = fn_to_test.inner_fn 
    excecpt AttributeError: 
    pass 
    return inner_fn() + 3 

この道をDRIVE API

result = get_drive_service().files().insert(body='body', convert=True).execute() 

ので、あなたは、関数を使ってパッチを適用する必要があります。

from mock import patch 
with patch('path.to.import.get_drive_service') as service_mock: 
    service_mock.return_value.files.return_value.insert.\ 
    return_value.execute.return_value = {'key': 'value', 'status': 200} 

主なスキーム: 最初service_mock()、ファイル()、最後の実行()レスポンスまで、)(挿入します。 return_value。秒。 return_value .third。 return_value .last。 return_value = rsp

+2

これは私の週末を保存しました。ネストされた属性は 'return_value'で連鎖される必要はないことに注意してください。 – Antwan