So senden Sie Anforderungen mit JSONs in Komponententests

95

Ich habe Code in einer Flask-Anwendung, die JSONs in der Anforderung verwendet, und ich kann das JSON-Objekt folgendermaßen abrufen:

Request = request.get_json()

Dies hat gut funktioniert, aber ich versuche, Unit-Tests mit Pythons unittest-Modul zu erstellen, und ich habe Schwierigkeiten, einen Weg zu finden, einen JSON mit der Anfrage zu senden.

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

Das gibt mir:

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

Flask scheint ein JSON-Argument zu haben, mit dem Sie json = dict (foo = 'bar') innerhalb der Post-Anfrage setzen können, aber ich weiß nicht, wie ich das mit dem unittest-Modul machen soll.

Sepehr Nazari
quelle
Was enthält das request.data? Wenn die JSON-Analyse aufgrund einer falschen Eingabe fehlschlägt, schlägt sie häufig stillschweigend fehl und gibt zurück, Nonesodass die rohen Eingabedaten möglicherweise nicht JSON sind.
Benoît Latinier
>>> request.get_data () '{"foo": "bar"}' >>> request.get_json () Keine Ich bin mir nicht ganz sicher, wie die Anfrage von flask funktioniert, aber sie scheint Daten und json und mich zu trennen Ich kann nicht herausfinden, wie Informationen an den JSON und nicht an die Daten gesendet werden sollen, wenn dies sinnvoll ist.
Sepehr Nazari
9
Ich denke, es sind die Header des Inhaltstyps. Versuchen Sie, sie auf appliacation / json zu setzen. Auch der Force-Parameter ist hilfreich, aber Sie möchten wahrscheinlich nicht dorthin gehen, nur um Unittests zu bestehen, sondern um Mime zu ändern
user3012759

Antworten:

192

Ändern des Beitrags in

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

behoben.

Vielen Dank an user3012759.

Sepehr Nazari
quelle
hat mir damit den Kopf kaputt gemacht. Sie verstehen nicht, warum Sie die Daten sichern müssen, wenn Sie bereits den application/jsonInhaltstyp angeben.
Dimmg
Ich glaube, das liegt daran, dass alles, was Sie in einem Beitrag senden, eine Zeichenfolge sein muss.
Sepehr Nazari
17
Erstaunlich, dass dies nicht in den Dokumenten enthalten ist, da der test_client von flask keine API-Dokumente enthält!
rjurney
Wie erhalte ich Daten aus der Antwort?
Variable
@variable, mit einer Antwort von einer post Anfrage, wie resp = client.post('/my/endpoint/',json=my_json_data)Sie mit Bytes auf die Daten zugreifen können resp.data.
Amiabl
44

UPDATE: Da die von Flask 1.0 freigegebenen flask.testing.FlaskClientMethoden jsonArgumente und Response.get_jsonhinzugefügte Methoden akzeptieren , siehe Beispiel .

Für Flask 0.x können Sie die folgende Quittung verwenden:

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
Victor Gavro
quelle
1
Und vergessen Sie nicht, dass das json-Argument dictkein JSON-String sein muss!
LaundroMat