Cómo enviar solicitudes con JSON en pruebas unitarias

96

Tengo un código dentro de una aplicación Flask que usa JSON en la solicitud, y puedo obtener el objeto JSON así:

Request = request.get_json()

Esto ha funcionado bien, sin embargo, estoy tratando de crear pruebas unitarias usando el módulo unittest de Python y tengo dificultades para encontrar una manera de enviar un JSON con la solicitud.

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

Esto me da:

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

Flask parece tener un argumento JSON en el que puede establecer json = dict (foo = 'bar') dentro de la solicitud de publicación, pero no sé cómo hacerlo con el módulo unittest.

Sepehr Nazari
fuente
¿Qué request.datacontiene? A menudo, cuando el análisis json falla debido a una entrada incorrecta, falla silenciosamente y regresa, por Nonelo que los datos de entrada sin procesar pueden no ser json.
Benoît Latinier
>>> request.get_data () '{"foo": "bar"}' >>> request.get_json () Ninguno No estoy muy seguro de cómo funciona la solicitud de flask, pero parece separar datos y json, y yo No puedo averiguar cómo enviar información al json en lugar de los datos, si eso tiene algún sentido.
Sepehr Nazari
9
Creo que son los encabezados de tipo de contenido, intente configurarlos en appliacation / json. también el parámetro de fuerza es útil, pero probablemente no quiera ir allí solo para hacer que pasen las
pruebas unitarias

Respuestas:

194

Cambiando la publicación a

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

arreglado.

Gracias a user3012759.

Sepehr Nazari
fuente
estaba destrozando mi cabeza con esto. No entiendo por qué tiene que volcar los datos cuando ya está especificando el application/jsontipo de contenido.
dimmg el
Creo que es porque todo lo que envías en una publicación tiene que ser una cadena.
Sepehr Nazari
17
Increíble, esto no está en los documentos, ¡porque test_client de flask no tiene documentos API!
rjurney
¿Cómo obtener datos de la respuesta?
variable
@variable, con una respuesta de una post solicitud como resp = client.post('/my/endpoint/',json=my_json_data)si pudiera acceder a los datos como bytes con resp.data.
amiabl
44

ACTUALIZACIÓN: Dado que los flask.testing.FlaskClientmétodos lanzados por Flask 1.0 aceptan jsonargumentos y Response.get_jsonmétodos agregados, vea el ejemplo .

para Flask 0.x puede usar el recibo a continuación:

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
Víctor Gavro
fuente
1
¡Y no olvide que el argumento json no debe ser una dictcadena JSON!
LaundroMat