Gunther
Gunther

Reputation: 2645

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'
    )

Upvotes: 6

Views: 2974

Answers (3)

mrj
mrj

Reputation: 629

Expanding on @davidism's answer, there is a particular case with the Authorization header: use the following form:

class CustomClient(FlaskClient):
    def open(self, *args, **kwargs):
        kwargs.setdefault('headers', {'Authorization': 'Bearer <token>'})
        return super().open(*args, **kwargs)

Upvotes: 0

Cas
Cas

Reputation: 6656

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()

Upvotes: 4

davidism
davidism

Reputation: 127310

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.

Upvotes: 7

Related Questions