私が使用するモッキング ライブラリは ... mockです。
関数(レガシーコード)のテストケースを書き込もうとしたときに、この「ネストされた関数のモック」の問題に遭遇しました。
この関数は、他のモジュールに大きく依存する非常に複雑なネストされた関数を使用していました。
でネストされた関数をモックすることは可能かどうか疑問に思いますmock
。
私が使用するモッキング ライブラリは ... mockです。
関数(レガシーコード)のテストケースを書き込もうとしたときに、この「ネストされた関数のモック」の問題に遭遇しました。
この関数は、他のモジュールに大きく依存する非常に複雑なネストされた関数を使用していました。
でネストされた関数をモックすることは可能かどうか疑問に思いますmock
。
たとえば、Google DRIVE API からネストされた関数呼び出し (連鎖関数) をモックする必要があります
result = get_drive_service().files().insert(body='body', convert=True).execute()
したがって、関数を通じてパッチを適用する必要があります: service_mock()、files()、insert()、最後の 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}
メインスキーム:最初。return_value .second. return_value .second. return_value .last. return_value = rsp
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
これを行うこともできます:
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
このようにして、オーバーライドを定義するだけです:
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
ネストされた関数をモック オブジェクトに置き換えようとしていますか? もしそうなら、関数がどれほど複雑であっても、それはかなり簡単です。MagicMockを使用して、ほぼすべての Python オブジェクトを置き換えることができます。
何かを返す関数をシミュレートする必要がある場合は、MagicMock
のreturn_value
パラメーターを設定するだけです。次のようになります。
>>> super_nested_mock = mock.MagicMock()
>>> super_nested_mock.return_value = 42
>>> super_nested_mock()
42
ただし、内部のどこかで関数を呼び出す別のコードをテストしようとしてsuper_nested
いて、それをモックアウトしたい場合は、patchを使用する必要があります。モック ライブラリでは、次のようになります。
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
ここでは、代わりにwith
通常呼び出すブロック内のすべてが を呼び出し、それに設定した値を返すだけです。super_nested
super_nested_mock
パッチ呼び出しに正確に何を入れる必要があるかについては、微妙な点があります。主に、テストしているモジュールがそれを見るように、オブジェクトにパッチを適用したいと考えています。詳細については、「パッチを適用する場所」を参照してください。
私が見た唯一の方法は、外部関数のコピーを動的に作成し、関数のコード オブジェクト定数をモック関数のコードで変更することです。