2017-11-24 21 views
0

私はモックで関数をユニットテストし、モックオブジェクトの呼び出しが行われたかどうかをテストしようとしています。下のコードではrequests.postオブジェクトが嘲笑され、requests.post.mock_callsのリストを追跡します。次のコードでpython mock.mock_callsは@timeout修飾された関数の中で行われた呼び出しに従いません

コードの構文:

import timeout_decorator 

def block_funds(trader_id, amounts): 

    @timeout_decorator.timeout(3, use_signals=False) 
    def _block_funds(block_url, amounts): 

     # requests.post.mock_calls empty here 
     result = requests.post(url=block_url, data=amounts) 
     # requests.post.mock_calls here has correct call recorded 

     return result.status_code 

    block_url = 'http:/someurl/somepath/{trader_id}'.format(trader_id=trader_id) 

    try: 

     # requests.post.mock_calls empty here 
     code = _block_funds(block_url, amounts) 
     # requests.post.mock_calls empty again here 

    except timeout_decorator.TimeoutError as ex: 
     logger.error('request failed') 
     code = 500 

    return code 
私はモックオブジェクトは、それへのすべてのコールの記録を保持することを期待 code = _block_funds(block_url, amounts)への呼び出しの後

が、mock_callsリストは、すぐに空にします実行が内部タイムアウトラップ関数_block_funds()を終了すると、モックオブジェクトは確かに同じですが、オブジェクトが変更されていないことを確認するために模擬IDに従っています。

私が間違ってやっていること、そしてモックを作る方法を呼び出すのを忘れることはありませんか?

+0

あなたのテストで比較して、関数内で値をテストしている1のために使用しているモックオブジェクトは、おそらく同じオブジェクトではありませんが。質問にテスト機能を含めてください。 – jordanm

+0

実際に私は原因を見つけました。これは '@ timeout'デコレータです。いいえ、オブジェクトは同じですが、私は模擬オブジェクトIDに従っていますが、タイムアウト・デコレータをコメントアウトするとすぐに、コールが表示され、テストに合格することがわかりました。私は今テストのための回避策を見つけなければなりません。 – alexykot

答えて

0

私はこの問題を発見しました。それはタイムアウトデコレータにあり、具体的には - use_signals=Falseの部分です。 timeout decorator documentationによれば、自分のシナリオ(マルチスレッドWebアプリケーション)でタイムアウトを正しく使用するには、信号を使用せずにマルチプロセッシングに頼る必要があります。この場合、予期しない問題が発生します。 use_signals=Falseを削除したり、デコレータを完全に削除したりすると、正常に動作します。

今私の解決策は、デコレータ自体をモックして問題を回避することです。直接デコレータをからかっ

補正は非現実的であることが判明しました。代わりに、私はそれを周りに包み、ラップ嘲笑しました:

def timeout_post(**kwargs): 
    @timeout_decorator.timeout(3, use_signals=False) 
    def _post(**kwargs): 
     return requests.post(**kwargs) 

    return _post(**kwargs) 
関連する問題