Django REST Framework单元测试报错:400 != 201 求助
解决POST接口单元测试返回400错误的问题
问题原因
你测试代码里的client.post把payload数据放到了请求体中,但你的接口实现是从URL查询参数(self.request.GET.get('text'))读取text值,导致接口根本没获取到数据,JokeSerializer验证时因joke字段缺失返回400错误。而直接在URL后拼接?text=Test%20Joke的方式能通过测试,是因为这种写法把数据正确放到了查询参数里,和接口的读取逻辑匹配。
解决方法
有两种修复路径可选:
方式一:适配现有接口的查询参数逻辑
修改测试代码,把text数据放到查询参数中传递,Django的APIClient支持通过query_params参数指定查询参数:
def test_post_joke(self): response = self.client.post('/api/jokes/add', query_params={'text': 'Test Joke'}) self.assertEqual(response.status_code, status.HTTP_201_CREATED)
也可以用format=None的方式传递:
def test_post_joke(self): response = self.client.post('/api/jokes/add', {'text': 'Test Joke'}, format=None) self.assertEqual(response.status_code, status.HTTP_201_CREATED)
方式二:调整接口逻辑(符合REST规范)
POST请求用查询参数传递创建数据不符合REST最佳实践,建议改成从请求体读取数据,更规范:
- 修改
AddJokeAPI的post方法:
def post(self, request): # 从请求体获取数据,替代查询参数 serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) joke = serializer.save() return Response({ "joke": JokeSerializer(joke, context=self.get_serializer_context()).data, "message": "New joke added", "success": True }, status=status.HTTP_201_CREATED)
- 更新Swagger文档,将参数类型改为请求体:
@swagger_auto_schema( operation_description="Guarda en una base de datos el chiste el texto pasado por parámetro", request_body=openapi.Schema( type=openapi.TYPE_OBJECT, properties={ 'joke': openapi.Schema(type=openapi.TYPE_STRING, description="Nuevo chiste") }, required=['joke'] ) )
- 对应的测试代码调整为传递请求体数据:
def test_post_joke(self): payload = { 'joke': 'Test Joke' # 字段名与serializer定义匹配 } response = self.client.post('/api/jokes/add', payload, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED)
总结
如果要保留现有接口的查询参数逻辑,用方式一修改测试即可;如果想遵循行业规范,推荐用方式二调整接口和测试,更符合POST请求传递数据的常规做法。
内容的提问来源于stack exchange,提问作者Luis Bermúdez
相关产品推荐
相关产品推荐

