简体   繁体   English

Flask 的 test_client 的类似请求的包装器

[英]requests-like wrapper for flask's test_client

I'm trying to make a usable tests for my package, but using Flask.test_client is so different from the requests API that I found it hard to use.我正在尝试为我的包进行可用的测试,但使用Flask.test_client与我发现很难使用的requests API 是如此不同。

I have tried to make requests.adapters.HTTPAdapter wrap the response, but it looks like werkzeug doesn't use httplib (or urllib for that matter) to build it own Response object.我试图让requests.adapters.HTTPAdapter包装响应,但看起来werkzeug不使用httplib (或urllib )来构建它自己的Response对象。

Any idea how it can be done?知道如何做到吗? Reference to existing code will be the best (googling werkzeug + requests doesn't give any useful results)参考现有代码将是最好的(谷歌搜索 werkzeug + requests 不会给出任何有用的结果)

Many thanks!!非常感谢!!

现在存在一个 PyPI 包,因此您可以使用pip install requests-flask-adapter

As I understood what you need is a mocking (see What is Mocking? and Mock Object ).我了解你需要的是一个嘲讽(见什么是嘲讽?Mock对象)。 Well, couple of your options listed below:好吧,下面列出了您的几个选项:

You can use the requests method defined in the code section below.您可以使用下面代码部分中定义的requests方法。 To use it you'll also need to define the get_auth_headers method shown in the code below.要使用它,您还需要定义下面代码中显示的get_auth_headers方法。

Features:特征:

  • Wrapper around the Flask test client. Flask 测试客户端的包装。
  • Automatically set the request headers.自动设置请求头。

    • Content-Type: Application/json when passing json Content-Type: Application/json传递json时的Content-Type: Application/json json
    • Basic Authentication constructed when passing auth .传递auth时构造的Basic Authentication auth
  • Dumps your json data as a string to the Flask test client.将您的json数据作为字符串转储到 Flask 测试客户端。
  • (Missing) Wrap the response into a requests.Response object (缺失)将响应包装到一个requests.Response对象中

Code:代码:

class MyTestCase(unittest.TestCase):
    def setUp(self):
        self.app = create_app('testing')
        self.client = self.app.test_client()
        self.app_context = self.app.app_context()
        self.app_context.push()
        db.create_all()

    def tearDown(self):
        db.session.remove()
        db.drop_all()
        self.app_context.pop()

    def get_auth_headers(self, username, password):
        return {
            'Authorization':
                'Basic ' + base64.b64encode(
                    (username + ':' + password).encode('utf-8')).decode('utf-8'),
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        }

    def requests(self, method, url, json={}, auth=(), **kwargs):
        """Wrapper around Flask test client to automatically set headers if JSON
        data is passed + dump JSON data as string."""
        if not hasattr(self.client, method):
            print("Method %s not supported" % method)
            return
        fun = getattr(self.client, method)

        # Set headers
        headers = {}
        if auth:
            username, password = auth
            headers = self.get_auth_headers(username, password)

        # Prepare JSON if needed
        if json:
            import json as _json
            headers.update({'Content-Type': 'application/json'})
            response = fun(url,
                           data=_json.dumps(json),
                           headers=headers,
                           **kwargs)
        else:
            response = fun(url, **kwargs)
        self.assertTrue(response.headers['Content-Type'] == 'application/json')
        return response

Usage (in a test case):用法(在测试用例中):

def test_requests(self):
    url = 'http://localhost:5001'
    response = self.requests('get', url)
    response = self.requests('post', url, json={'a': 1, 'b': 2}, auth=('username', 'password'))
    ...

The only difference with requests is that instead of typing requests.get(...) you'll have to type self.request('get', ...) .requests的唯一区别是,您必须输入self.request('get', ...)而不是键入requests.get(...) self.request('get', ...)

If you really want requests behaviour, you'll need to define your own get , put , post , delete wrappers around requests如果你真的想要requests行为,你需要定义你自己的getputpostdelete围绕requests包装器

Note:笔记:

An optimal way to do this might be to subclass FlaskClient as described in Flask API documentation执行此操作的最佳方法可能是按照Flask API 文档中的描述对FlaskClient进行子类FlaskClient

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM