在Flask的接口开发中,经常需要通过request.get_json获取前端传递的JSON格式请求数据,编写单元测试时如果直接调用接口而不做模拟,很容易因为请求格式不符合要求导致测试失败,因此需要掌握正确的模拟方式。

基础模拟方式:使用test_client设置JSON数据
Flask内置的test_client提供了直接发送JSON请求的能力,不需要额外做复杂的模拟,只需要在请求时传入json参数即可,此时request.get_json会自动解析传入的JSON数据。
先来看一个需要测试的Flask接口示例:
from flask import Flask, request
app = Flask(__name__)
@app.route('/api/user', methods=['POST'])
def create_user():
data = request.get_json()
username = data.get('username')
age = data.get('age')
if not username or not age:
return {'msg': '参数缺失'}, 400
return {'msg': '创建成功', 'user': {'username': username, 'age': age}}, 200
对应的单元测试代码如下:
import unittest
from app import app
class TestCreateUser(unittest.TestCase):
def setUp(self):
self.app = app.test_client()
self.app.testing = True
def test_create_user_success(self):
# 直接传入json参数,test_client会自动设置正确的请求头和请求体
response = self.app.post('/api/user', json={'username': '张三', 'age': 20})
self.assertEqual(response.status_code, 200)
self.assertEqual(response.get_json()['msg'], '创建成功')
def test_create_user_missing_param(self):
# 传入缺失参数的JSON数据
response = self.app.post('/api/user', json={'username': '李四'})
self.assertEqual(response.status_code, 400)
if __name__ == '__main__':
unittest.main()
特殊场景模拟:手动构造请求头和请求体
如果需要在不使用json参数的场景下模拟,比如测试自定义的请求解析逻辑,就需要手动设置请求头Content-Type为application/json,同时将JSON数据序列化为字符串作为请求体。
对应的测试代码示例如下:
import json
import unittest
from app import app
class TestCreateUserManual(unittest.TestCase):
def setUp(self):
self.app = app.test_client()
self.app.testing = True
def test_manual_json_request(self):
# 手动构造JSON请求
headers = {'Content-Type': 'application/json'}
data = json.dumps({'username': '王五', 'age': 25})
response = self.app.post('/api/user', headers=headers, data=data)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.get_json()['user']['username'], '王五')
使用unittest.mock模拟request.get_json
如果接口中request.get_json的调用逻辑比较复杂,或者需要模拟异常情况,比如解析失败的场景,可以使用unittest.mock来直接模拟request.get_json的返回值。
示例代码如下:
from unittest.mock import patch
import unittest
from app import app
class TestMockGetJson(unittest.TestCase):
def setUp(self):
self.app = app.test_client()
self.app.testing = True
@patch('app.request')
def test_mock_get_json_return(self, mock_request):
# 模拟request.get_json的返回值
mock_request.get_json.return_value = {'username': '赵六', 'age': 30}
# 不需要传入真实JSON数据,因为get_json已经被模拟
response = self.app.post('/api/user')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.get_json()['user']['age'], 30)
@patch('app.request')
def test_mock_get_json_exception(self, mock_request):
# 模拟get_json抛出异常的场景
mock_request.get_json.side_effect = ValueError('JSON解析失败')
response = self.app.post('/api/user')
# 这里可以根据接口的实际异常处理逻辑调整断言
self.assertEqual(response.status_code, 400)
常见错误与规避方法
- 错误1:忘记设置
Content-Type为application/json,直接传入JSON字符串作为请求体,此时request.get_json会返回None。规避方法:要么使用json参数自动设置,要么手动添加正确的请求头。 - 错误2:模拟时路径不正确,比如接口在
views.user模块中导入request,却patch了flask.request,导致模拟不生效。规避方法:patch的路径要和接口中导入request的路径一致。 - 错误3:测试时没有开启
testing模式,导致部分错误没有被正确抛出。规避方法:初始化test_client后设置self.app.testing = True。
不同模拟方式的选择建议
如果是测试正常的接口逻辑,优先使用test_client的json参数,这种方式最接近真实请求场景,测试可信度更高。如果需要模拟异常场景或者复杂的返回值逻辑,再选择unittest.mock进行模拟。手动构造请求头和请求体的方式适合需要验证请求格式解析逻辑的场景,日常测试中不推荐优先使用。
Flask单元测试request_get_json模拟请求修改时间:2026-07-15 19:06:35