Django DRF API 单元测试完整方案(基于 `TestCase`)

Django DRF API 单元测试完整方案(基于 TestCase

一、方案概述

使用 django.test.TestCaserest_framework.test.APIClient 进行 API 单元测试 ,确保 API 正确性、权限控制、数据返回格式、业务逻辑 等。


二、基本步骤

  1. 使用 setUp() 初始化测试环境

    • 创建 API 客户端 APIClient()
    • 预先插入数据库测试数据(如普通用户、管理员用户等)
    • 生成 Token 进行身份认证(如 TokenAuthentication
  2. 编写测试用例

    • 发送 GETPOSTPUTDELETE 请求
    • 断言 HTTP 状态码、数据格式、权限逻辑等
  3. 运行测试

    • 执行 python manage.py test 运行测试

三、测试场景 1:权限控制(用户管理 API)

HTTP 方法 端点 功能描述
POST /api/users/ 创建用户
GET /api/users/ 获取用户列表(需要身份认证)
GET /api/users/{id}/ 获取用户详情(仅管理员可查看)
PUT /api/users/{id}/ 更新用户信息(仅限用户本人)
DELETE /api/users/{id}/ 删除用户(仅管理员可删除)

完整的 API 测试代码

python 复制代码
from django.test import TestCase
from rest_framework.test import APIClient
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token

class UserAPITestCase(TestCase):
    """用户 API 测试"""

    def setUp(self):
        """初始化 API 客户端,并创建测试用户和管理员"""
        self.client = APIClient()

        # 创建普通用户
        self.user = User.objects.create_user(username="testuser", email="test@example.com", password="password123")

        # 创建管理员用户
        self.admin_user = User.objects.create_superuser(username="admin", email="admin@example.com", password="adminpass")

        # 生成 Token
        self.token, _ = Token.objects.get_or_create(user=self.user)
        self.admin_token, _ = Token.objects.get_or_create(user=self.admin_user)

    def test_get_users_without_authentication(self):
        """测试未登录获取用户列表,应该返回 403"""
        response = self.client.get("/api/users/")
        self.assertEqual(response.status_code, 403)

    def test_get_users_with_authentication(self):
        """测试登录后获取用户列表"""
        self.client.credentials(HTTP_AUTHORIZATION=f"Token {self.token.key}")
        response = self.client.get("/api/users/")
        self.assertEqual(response.status_code, 200)

四、测试场景 2:API 依赖前置 setUp()(菜品管理 API)

HTTP 方法 端点 功能描述
POST /api/categories/ 创建菜品分类
GET /api/categories/ 获取菜品分类列表
POST /api/dishes/ 创建菜品(必须指定已有的菜品分类)
GET /api/dishes/ 获取菜品列表

完整的 API 测试代码

python 复制代码
from django.test import TestCase
from rest_framework.test import APIClient
from myapp.models import Category, Dish

class DishAPITestCase(TestCase):
    """菜品 API 测试"""

    def setUp(self):
        """初始化 API 客户端,并创建测试数据"""
        self.client = APIClient()
        # 创建一个分类
        self.category = Category.objects.create(name="热菜")

    def test_create_dish_with_valid_category(self):
        """测试创建菜品(分类有效)"""
        data = {"name": "宫保鸡丁", "price": "25.00", "category": self.category.id}
        response = self.client.post("/api/dishes/", data, format="json")
        self.assertEqual(response.status_code, 201)
        self.assertEqual(response.data["name"], "宫保鸡丁")

    def test_create_dish_with_invalid_category(self):
        """测试创建菜品(分类不存在)"""
        data = {"name": "鱼香肉丝", "price": "22.00", "category": 999}  # 不存在的分类 ID
        response = self.client.post("/api/dishes/", data, format="json")
        self.assertEqual(response.status_code, 400)
        self.assertIn("分类不存在", response.data["category"])

五、运行测试

bash 复制代码
python manage.py test myapp

六、方案总结

功能 方法 断言
获取用户列表(未登录) test_get_users_without_authentication() self.assertEqual(response.status_code, 403)
获取用户列表(已登录) test_get_users_with_authentication() self.assertEqual(response.status_code, 200)
创建菜品(分类有效) test_create_dish_with_valid_category() self.assertEqual(response.status_code, 201)
创建菜品(分类不存在) test_create_dish_with_invalid_category() self.assertEqual(response.status_code, 400)

覆盖了权限控制 + API 依赖数据,确保 Django DRF API 的稳定性

相关推荐
学长毕业设计4 小时前
基于SpringBoot的公益基金管理系统(源码+文档+讲解视频)
java·spring boot·后端
东小西4 小时前
【SAA实战】第 3 篇 · 工具调用全攻略:把业务能力交给 Agent 自己调度
java·后端·spring
东小西4 小时前
【SAA实战】第 4 篇 · Agent 短期记忆:saver 让 Agent 跨轮记得住(threadId 隔离)
java·后端·spring
阿kun要赚马内5 小时前
MySQL 索引基础
后端·mysql
码事漫谈5 小时前
我啥都能做,却不知道做什么了
后端
geovindu5 小时前
CSharp: 万年历
开发语言·后端·c#·.net
独泪了无痕7 小时前
SpringBoot Event事件机制,轻松实现业务解耦
spring boot·后端·spring
悲且狂8 小时前
SpringBoot项目改造注意事项(旧项目框架复用)
java·spring boot·后端
敲代码的嘎仔9 小时前
28届后端开发-海康威视日常实习一面(已OC)
java·开发语言·后端·面试·海康威视·实习·大厂
IT_陈寒9 小时前
JavaScript数组排序踩的坑,差点让我加班到凌晨
前端·人工智能·后端