2017-12-03 4 views
-1

Flask route()で装飾されたメソッドが呼び出されるかどうかをユニットテストする必要があります。Python Flaskで装飾されたメソッドを模擬する方法route()

なしで、可能であれば元のコードを修正していないので、メソッドをモックすると完全にスイートになります。

そこで私は、装飾されたリクエストメソッドを模擬する方法についてこの特定質問(私はあまり具体的な答えを自分の時間を無駄に人を回避しようとするために、これを強調したい)...

サンプル・アプリケーションを求めていますjflask.py :私は、私はそれが呼ばれた主張できるよう方法を模擬するために@patch()を使用していますが、アサーションが失敗したユニットテストで

from flask import Flask 
app = Flask(__name__) 
app.config.from_object(__name__) 

@app.route('/hello')   # This method represents the code under test. 
def hello():     # I want to assert that this method gets 
    return 'Hello, World'  # called without modifying this code. 

if __name__ == "__main__": 
    app.run() 

。私。モックメソッドは呼び出されません、私はそれを期待します。

サンプルユニットテストtest_hello.py:私は間違って

import unittest 
import jflask 
from unittest.mock import patch 

class jTest(unittest.TestCase): 
    def setUp(self): 
     #jflask.app.testing = True 
     self.app = jflask.app.test_client() 

    @patch('jflask.hello')    # mock the hello() method 
    def test_hello(self, mock_method): 
     rv = self.app.get('/hello') 
     mock_method.assert_called() # this assertion fails 

をしていますか?


背景

(上記は単なる凝縮テストケースで、それ自体によって完全に正気思えないかもしれないので)私は をテストしようとしている実際行動に関するいくつかの背景情報。

私がユニットテストを行っている実際のコードには、before_request()ハンドブック がインストールされています。これは、各リクエストが処理される前にFlaskによって呼び出され、 の場合、このハンドラは応答値を返すように設計されています(このアプリケーションの場合、この機能は要求パラメータを集中的に検証するために使用されます) )、通常のルーティングされたリクエストハンドラが(意図的に)呼び出されないようにします。

私のユニットテストでは、要求処理が停止したことをアサートする必要があります(状況によっては、 )。 したがって、私のテストでは、実際のリクエストハンドラを模擬して、 が呼び出されたかどうかを確認する必要があります。

+2

モックが適用されます* *ときについて考える - あなたはすでにテスト中のコードで定義を実行してきた、フラスコは*オリジナル 'hello' *が登録されています。これはあなたのコードではなくフレームワークをテストすることに非常に近いと思われ、動作ではなく実装をテストしています。特定のメソッドが呼び出されているかどうかにかかわらず、正しい*応答*を取得することをテストしてください。 – jonrsharpe

+0

@jonrsharpe、上記のコードは単なるテストケースの縮小です - それはそれだけではあまり意味がないことを理解しています。実際のコードでは、メソッドをモックすることを余儀なくされているので、レスポンスのテストはオプションではありません。実際にリクエストメソッドが呼び出されるかどうかに影響を与える、 'before_request()'ハンドラがアプリケーションにインストールされています。これはテストする必要がある動作です。 – Lqueryvg

+1

おそらく、テストしようとしている*実際の動作について話すことは役に立ちます。さもなければあなたは[XY問題](http://xyproblem.info)への解決を得る危険にさらされます。 – jonrsharpe

答えて

0

これは少しハッキリですが、ロガーを挿入することができます。

@app.route(...): 
def hello(logger=None): 
    logger = logger or self.logger 
    logger.info(...) 
    return ... 

def test_...(self): 
    logger = MagicMock() 
    self.app.get(logger) 
    self.assertTrue(logger.info.called) 
+0

可能であれば、テスト中のコード( 'hello()'メソッドを変更しないでください。 – Lqueryvg

1
from functools import wraps 
import logging 
from datetime import datetime 
logging.basicConfig(filename=datetime.now().strftime('%d_%m_%Y.log'),level=logging.INFO) 

def logger_required(f): 
    @wraps(f) 
    def decorated(*args, **kwargs): 
     logging.info(f.__name__ + ' was called') 
     return f(*args, **kwargs) 
    return decorated 

@app.route('/hello') 
@logger_required 
def hello():     # I want to assert that this gets called 
    return 'Hello, World' 
+0

これは現在のディレクトリにテキストファイルを作成し、ログの下にあります 情報:root:helloが呼び出されました –

+0

テスト中のシステム(コード)を変更せずにこれを実行したいことを明確にするために質問を更新しました。これが私の具体的な質問がPython Flask route()で装飾されたメソッドをどうやって模擬するかということです。 – Lqueryvg

関連する問題