Как отправлять запросы с JSON в модульных тестах

100

У меня есть код в приложении Flask, которое использует JSON в запросе, и я могу получить объект JSON следующим образом:

Request = request.get_json()

Это работает нормально, однако я пытаюсь создать модульные тесты с использованием модуля Python unittest, и мне трудно найти способ отправить 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.
Benoît Latinier
>>> request.get_data () '{"foo": "bar"}' >>> request.get_json () Нет Я не совсем уверен, как работает запрос flask, но, похоже, он разделяет данные и json, и я не могу понять, как отправлять информацию в json, а не данные, если это имеет смысл.
Sepehr Nazari 03
9
Я думаю, что это заголовки типа контента, попробуйте установить их в application / json. также полезен параметр force, но вы, вероятно, не хотите идти туда только для того, чтобы пройти unittests, лучше изменить mime
user3012759

Ответы:

199

Изменение сообщения на

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

починил это.

Спасибо user3012759.

Сепер Назари
источник
ломал мне голову этим. Не понимаю, почему вам нужно сбрасывать данные, когда вы уже указываете application/jsonтип контента.
dimmg
Я считаю, это потому, что все, что вы отправляете в сообщении, должно быть строкой.
Sepehr Nazari
18
Удивительно, но этого нет в документации, потому что test_client flask не имеет документации API!
rjurney
Как получить данные из ответа?
переменная
@variable, с ответом на post запрос, например, resp = client.post('/my/endpoint/',json=my_json_data)вы можете получить доступ к данным в виде байтов с помощью resp.data.
amiabl
44

ОБНОВЛЕНИЕ: поскольку выпущенные flask.testing.FlaskClientметоды Flask 1.0 принимают 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 не должен быть dictстрокой JSON!
LaundroMat