You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django REST Framework接口测试失败:test_create_post断言错误

接口测试失败排查:test_create_post返回400而非201

问题场景

编写接口测试时,test_create_post用例持续失败,返回400状态码,预期结果为201。

测试代码(test.py)

from rest_framework.test import APITestCase, APIRequestFactory
from rest_framework import status
from django.urls import reverse
from .views import PostViewSet
from django.contrib.auth import get_user_model

User = get_user_model()


class PostListCreateTestCase(APITestCase):
    def setUp(self):
        self.factory = APIRequestFactory()
        self.view = PostViewSet.as_view({"get": "list", "post": "create"})
        self.url = reverse("post_list")
        self.user = User.objects.create(
            email="testuser@gmail.com", name="testuser", password="pass"
        )

    def test_list_posts(self):
        request = self.factory.get(self.url)
        response = self.view(request)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_create_post(self):
        sample_post = {
            "title": "sample title",
            "body": "sample body",
        }
        request = self.factory.post(self.url, sample_post)
        request.user = self.user
        response = self.view(request)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

视图代码

from rest_framework import viewsets, status
from rest_framework.response import Response
from django.shortcuts import get_object_or_404
from .serializers import PostSerializer, LikeSerializer
from .models import Post, Like


class PostViewSet(viewsets.ModelViewSet):
    serializer_class = PostSerializer
    queryset = Post.objects.all()

    def get_queryset(self):
        posts = Post.objects.all()
        return posts

    def get_object(self):
        post = get_object_or_404(self.get_queryset(), pk=self.kwargs["pk"])
        self.check_object_permissions(self.request, post)
        return post

    def create(self, request, *args, **kwargs):
        try:
            post = Post.objects.create(
                title=request.data.get("title"),
                body=request.data.get("body"),
                author=request.user,
            )
            post = PostSerializer(post)
            return Response(post.data, status=status.HTTP_201_CREATED)
        except Exception as ex:
            return Response(str(ex), status=status.HTTP_400_BAD_REQUEST)

    def list(self, request, *args, **kwargs):
        posts = self.get_queryset()
        serializer = self.get_serializer(posts, many=True)
        return Response(
            data=dict(posts=serializer.data, total=len(serializer.data)),
            status=status.HTTP_200_OK,
        )

测试结果

Found 2 test(s). Creating test database for alias 'default'... System
check identified no issues (0 silenced). F.
====================================================================== FAIL: test_create_post (posts.tests.PostListCreateTestCase)
---------------------------------------------------------------------- Traceback (most recent call last): File
"/home/amr/Snakat/social_network/posts/tests.py", line 31, in
test_create_post
self.assertEqual(response.status_code, status.HTTP_201_CREATED) AssertionError: 400 != 201

---------------------------------------------------------------------- Ran 2 tests in 0.023s

FAILED (failures=1) Destroying test database for alias 'default'...

排查与修复步骤

1. 先获取具体错误信息

视图的create方法捕获所有异常并返回字符串,但测试代码未输出错误详情。修改测试用例添加打印语句:

def test_create_post(self):
    sample_post = {
        "title": "sample title",
        "body": "sample body",
    }
    request = self.factory.post(self.url, sample_post)
    request.user = self.user
    response = self.view(request)
    print("错误详情:", response.data)  # 新增此行
    self.assertEqual(response.status_code, status.HTTP_201_CREATED)

运行测试后即可看到具体错误原因,比如用户创建问题、字段约束问题等。

2. 修复用户创建方式

直接用User.objects.create设置密码会存储明文,不符合Django用户模型规范,应改用create_user方法,该方法会自动哈希密码并确保字段验证通过:

# 在setUp方法中修改用户创建代码
self.user = User.objects.create_user(
    email="testuser@gmail.com", name="testuser", password="pass"
)

3. 规范视图的create方法(可选但推荐)

当前视图直接创建数据库对象,跳过了序列化器的验证逻辑,容易忽略数据合法性问题。改用DRF标准的序列化器验证流程:

def create(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    # 将当前用户作为author传入
    serializer.save(author=request.user)
    return Response(serializer.data, status=status.HTTP_201_CREATED)

此方式不仅能自动处理数据验证,还能返回结构化的错误信息,方便调试。

4. 检查请求内容类型(若需要)

如果视图期望接收JSON格式数据,需在构造请求时指定content_type:

import json

# 在test_create_post中修改请求构造代码
request = self.factory.post(
    self.url,
    json.dumps(sample_post),
    content_type='application/json'
)

内容的提问来源于stack exchange,提问作者Raskolnikov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 22:40:31