Comment envoyer des requêtes avec des JSON dans des tests unitaires

96

J'ai du code dans une application Flask qui utilise des JSON dans la demande, et je peux obtenir l'objet JSON comme suit:

Request = request.get_json()

Cela fonctionne bien, mais j'essaie de créer des tests unitaires à l'aide du module unittest de Python et j'ai du mal à trouver un moyen d'envoyer un JSON avec la demande.

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

Cela me donne:

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

Flask semble avoir un argument JSON où vous pouvez définir json = dict (foo = 'bar') dans la demande de publication, mais je ne sais pas comment faire cela avec le module unittest.

Sepehr Nazari
la source
Que request.datacontient le? Souvent, lorsque l'analyse json échoue en raison d'une mauvaise entrée, elle échoue silencieusement et renvoie Noneainsi les données d'entrée brutes peuvent ne pas être json.
Benoît Latinier
>>> request.get_data () '{"foo": "bar"}' >>> request.get_json () Aucun Je ne suis pas sûr du fonctionnement de la requête de flask, mais il semble séparer les données et json, et je ne peut pas comprendre comment envoyer des informations au json plutôt que les données, si cela a un sens.
Sepehr Nazari
9
Je pense que ce sont les en-têtes de type de contenu, essayez de les définir sur appliacation / json. le paramètre force est également utile mais vous ne voulez probablement pas y aller juste pour faire passer les tests, mieux vaut changer de mime
user3012759

Réponses:

194

Changer le message en

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

réparé.

Merci à user3012759.

Sepehr Nazari
la source
me détruisait la tête avec ça. Je ne comprends pas pourquoi vous devez vider les données lorsque vous spécifiez déjà le application/jsontype de contenu.
dimmg
Je crois que c'est parce que tout ce que vous envoyez dans un message doit être une chaîne.
Sepehr Nazari
17
Étonnant que ce ne soit pas dans la documentation, car le test_client de flask n'a pas de documentation API!
rjurney
Comment obtenir des données de la réponse?
variable du
@variable, avec une réponse à une post requête comme resp = client.post('/my/endpoint/',json=my_json_data)vous pouvez accéder aux données sous forme d'octets avec resp.data.
amiabl le
44

MISE À JOUR: Puisque les flask.testing.FlaskClientméthodes publiées par Flask 1.0 acceptent l' jsonargument et la Response.get_jsonméthode ajoutés, voir l' exemple .

pour Flask 0.x, vous pouvez utiliser le reçu ci-dessous:

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
la source
1
Et n'oubliez pas que l'argument json ne doit pas être une dictchaîne JSON!
LaundroMat