Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask.test_client().post and JSON encoding

I am writing test cases for JSON endpoints in a Flask app.

import unittest
from flask import json
from app import create_app


class TestFooBar(unittest.TestCase):
    def setUp(self):
        self.app = create_app('testing')
        self.app_context = self.app.app_context()
        self.app_context.push()

    def test_ham(self):
        resp = self.client.post('/endpoint',
                                headers={'Content-Type': 'application/json'},
                                data=json.dumps({'foo': 2,
                                                 'bar': 3}))
        assert resp.status_code == 200

    def test_eggs(self):
        resp = self.client.post('/endpoint', data={'foo': 5,
                                                   'bar': 7})
        assert resp.status_code == 200

    def test_ham_and_eggs(self):
        with self.app.test_client() as self.client:
            self.test_ham()
            self.test_eggs()

Just to understand what's happening, do both ways of sending a POST message in the code above make sense? In particular, am I double-JSON encoding in the first case?

Or, briefly, what is the difference between test_ham and test_eggs? Is there any?

like image 380
Calaf Avatar asked Sep 12 '25 05:09

Calaf


1 Answers

You are not double-encoding JSON, no, because data doesn't encode anything to JSON. test_ham posts JSON, test_eggs does not.

Starting from Flask 1.0, the Flask test client supports posting JSON directly, via the json keyword argument, use it to cut down on boilerplate code here:

def test_ham(self):
    resp = self.client.post('/endpoint', json={'foo': 2, 'bar': 3})
    assert resp.status_code == 200

See the Testing JSON APIs section of the Flask Testing documentation chapter:

Passing the json argument in the test client methods sets the request data to the JSON-serialized object and sets the content type to application/json.

Passing a dictionary to data produces a different kind of request, a application/x-www-form-urlencoded encoded request just like a <form method="POST" ...> form would produce from your browser, and the foo and bar values would have to be accessed via the request.form object. Do not use it when posting JSON is needed.

like image 70
Martijn Pieters Avatar answered Sep 13 '25 20:09

Martijn Pieters