Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set default content_type for Flask test client

Is there a way to set the default content_type value for the test client in Flask?

For example, if I have the following test:

import unittest

class MyTestCase(unittest.TestCase):

    def setUp(self):
        from my_flask_project import app
        self.client = app.test_client()

    def test_request_one(self):
        self.client.post(
            data='{}'
            content_type='application/json'
        )

    def test_request_two(self):
        self.client.post(
            data='{}'
            content_type='application/json'
        )

All of my test cases are going to set content_type='application/json'. I would like to set application/json as the default content type for requests but I couldn't find any documentation on how to do this.

Something like this would be ideal:

def setUp(self):
    from my_flask_project import app
    self.client = app.test_client(
        default_content_type='application/json'
    )
like image 921
Gunther Avatar asked Dec 12 '17 15:12

Gunther


2 Answers

For most headers, you can pass an environ_base dict to set other headers. However, the test client will always set the Content-Type header to the value passed in, overriding the base. There's also environ_overrides, which can override that override, but that means you can't set the header to anything else, which is probably not what you want.

Create a custom TestClient class that sets a default content type if one is not passed. Assign that class to your Flask app test_client_class and it will use it when creating test clients.

from flask.testing import FlaskClient

class CustomClient(FlaskClient):
    def open(self, *args, **kwargs):
        kwargs.setdefault('content_type', 'application/json')
        return super().open(*args, **kwargs)

app.test_client_class = CustomClient

You can use this technique for any arg, not just content_type, including environ_base.

like image 92
davidism Avatar answered Sep 22 '22 17:09

davidism


I found a simpler solution is to use the Client parameter json instead of data. This way it is explicit what data you are sending but don't need to set/override the header.

From the Flask docs:

A shortcut when testing JSON APIs is to pass a dict to json instead of using data. This will automatically call json.dumps() and set the content type to application/json. Additionally, if the app returns JSON, response.json will automatically call json.loads().

response = client.post("/api", json={"a": "value", "b": 1})
obj = response.json()
like image 21
Cas Avatar answered Sep 21 '22 17:09

Cas