如何在单元测试中使用JSON发送请求


96

我在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。
伯努瓦Latinier

>>> request.get_data()'{“ foo”:“ bar”}'>>> request.get_json()无我不太确定flask的请求如何工作,但是它似乎将数据和json分开了,我如果有意义的话,就无法弄清楚如何将信息发送到json而不是数据。
Sepehr Nazari'3

9
我认为这是内容类型标头,请尝试将其设置为appliacation / json。力参数也很有用,但是您可能不想去那里只是为了使单元测试通过,最好更改mime
user3012759 2015年

Answers:


193

将帖子更改为

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

解决它。

感谢user3012759。


我为此感到头疼。不明白为什么已经指定application/json内容类型时必须转储数据。
dimmg '16

我相信这是因为您在帖子中发送的所有内容都必须是字符串。
Sepehr Nazari

17
令人惊讶的是这不在文档中,因为flask的test_client没有API文档!
rjurney

如何从响应中获取数据?
变量

@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添加的方法,请参见example

对于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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.