単体テストでJSONを使用してリクエストを送信する方法


96

リクエストでJSONを使用するFlaskアプリケーション内にコードがあり、次のようにJSONオブジェクトを取得できます。

Request = request.get_json()

これは問題なく動作していますが、Pythonのユニットテストモジュールを使用してユニットテストを作成しようとしており、リクエストでJSONを送信する方法を見つけるのが困難です。

response=self.app.post('/test_function', 
                       data=json.dumps(dict(foo = 'bar')))

これは私に与えます:

>>> request.get_data()
'{"foo": "bar"}'
>>> request.get_json()
None

Flaskには、JSON引数があり、投稿リクエスト内でjson = dict(foo = 'bar')を設定できるようですが、unittestモジュールでそれを行う方法がわかりません。


何がrequest.data含まれていますか?多くの場合、誤った入力が原因でjsonの解析が失敗すると、それは警告なしに失敗し、返されるNoneため、生の入力データはjsonではない場合があります。
ブノワLatinier

>>> request.get_data() '{"foo": "bar"}' >>> request.get_json()なしフラスコのリクエストがどのように機能するかはよくわかりませんが、データとjsonを分離しているようです。理にかなっている場合、データではなくjsonに情報を送信する方法を理解できません。
Sepehr Nazari、2015

9
私はそれがコンテンツタイプのヘッダーだと思うので、それらをappliacation / jsonに設定してみてください。また、forceパラメータも役に立ちますが、おそらく単体テストに合格するためにそこに行きたくないので、mimeを変更した方が良いでしょう
user3012759

回答:


193

投稿を

response=self.app.post('/test_function', 
                       data=json.dumps(dict(foo='bar')),
                       content_type='application/json')

修正しました。

user3012759に感謝します。


これで頭をぐちゃぐちゃにしていた。application/jsonコンテンツタイプを既に指定しているのに、なぜデータをダンプする必要があるのか​​理解できません。
dimmg 2016年

投稿で送信するものはすべて文字列でなければならないためだと思います。
Sepehr Nazari、2016

17
素晴らしいです。フラスコのtest_clientにはAPIドキュメントがないためです。
rjurney 2018年

応答からデータを取得する方法は?
変数

@variable、post リクエストからの応答をresp = client.post('/my/endpoint/',json=my_json_data)使用して、でデータをバイトとしてアクセスできますresp.data
amiabl

44

更新: Flask 1.0でリリースされたflask.testing.FlaskClientメソッドはjson引数とResponse.get_jsonメソッドの追加を受け入れるため、例を参照してください。

Flask 0.xの場合、以下のレシートを使用できます。

from flask import Flask, Response as BaseResponse, json
from flask.testing import FlaskClient
from werkzeug.utils import cached_property


class Response(BaseResponse):
    @cached_property
    def json(self):
        return json.loads(self.data)


class TestClient(FlaskClient):
    def open(self, *args, **kwargs):
        if 'json' in kwargs:
            kwargs['data'] = json.dumps(kwargs.pop('json'))
            kwargs['content_type'] = 'application/json'
        return super(TestClient, self).open(*args, **kwargs)


app = Flask(__name__)
app.response_class = Response
app.test_client_class = TestClient
app.testing = True

1
そして、json引数はdictJSON文字列でなければならないことを忘れないでください!
LaundroMat
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.