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?
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 toapplication/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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With