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

Django ModelForm含ModelChoiceField的测试用例编写问询

编写Django AppleOrangeAssignmentForm的测试用例

没问题,针对你这个表单,我们可以从核心业务逻辑出发,覆盖几个关键测试场景,确保表单行为完全符合预期。下面是具体的测试思路和代码示例:

测试核心场景

我们需要重点验证这几个关键点:

  • 表单初始化时,下拉选项仅展示未分配给任何Apple的Orange实例
  • 提交有效数据后,Orange能正确关联到目标Apple
  • 必填字段验证正常(未选择Orange时表单报错)
  • 尝试手动提交已分配的Orange ID时,表单能识别并拒绝

完整测试代码示例

from django.test import TestCase
from .models import Apple, Orange
from .forms import AppleOrangeAssignmentForm

class AppleOrangeAssignmentFormTest(TestCase):
    def setUp(self):
        # 提前准备测试数据:已分配/未分配的Orange,以及测试用Apple
        self.unassigned_orange1 = Orange.objects.create(name="未分配橙子1")
        self.unassigned_orange2 = Orange.objects.create(name="未分配橙子2")
        
        self.assigned_apple = Apple.objects.create(name="已关联苹果")
        self.assigned_orange = Orange.objects.create(name="已分配橙子", apple=self.assigned_apple)
        
        self.test_apple = Apple.objects.create(name="待分配苹果")

    def test_form_queryset_only_shows_unassigned_oranges(self):
        # 初始化表单
        form = AppleOrangeAssignmentForm(instance=self.test_apple)
        # 提取下拉选项里的所有Orange ID
        form_orange_ids = [choice[0] for choice in form.fields['orange'].queryset.values_list('id', flat=True)]
        
        # 验证未分配的Orange在选项中,已分配的不在
        self.assertIn(self.unassigned_orange1.id, form_orange_ids)
        self.assertIn(self.unassigned_orange2.id, form_orange_ids)
        self.assertNotIn(self.assigned_orange.id, form_orange_ids)

    def test_form_valid_submission_assigns_orange_to_apple(self):
        # 构造有效表单数据
        form_data = {'orange': self.unassigned_orange1.id}
        form = AppleOrangeAssignmentForm(instance=self.test_apple, data=form_data)
        
        # 验证表单有效并保存
        self.assertTrue(form.is_valid())
        form.save()
        
        # 刷新数据库实例,确认关联关系生效
        self.test_apple.refresh_from_db()
        self.assertEqual(self.test_apple.orange, self.unassigned_orange1)
        
        # 额外验证:该Orange现在已被分配,不会出现在后续表单的选项中
        new_form = AppleOrangeAssignmentForm(instance=self.test_apple)
        new_form_orange_ids = [choice[0] for choice in new_form.fields['orange'].queryset.values_list('id', flat=True)]
        self.assertNotIn(self.unassigned_orange1.id, new_form_orange_ids)

    def test_form_invalid_when_no_orange_selected(self):
        # 提交空的orange字段
        form_data = {'orange': ''}
        form = AppleOrangeAssignmentForm(instance=self.test_apple, data=form_data)
        
        # 验证表单无效,且有对应的必填错误提示
        self.assertFalse(form.is_valid())
        self.assertIn('orange', form.errors)
        self.assertEqual(form.errors['orange'][0], 'This field is required.')

    def test_form_invalid_when_assigning_already_assigned_orange(self):
        # 手动构造已分配Orange的ID提交(模拟前端绕过下拉的恶意场景)
        form_data = {'orange': self.assigned_orange.id}
        form = AppleOrangeAssignmentForm(instance=self.test_apple, data=form_data)
        
        # 验证表单无效,因为该Orange不在合法的queryset范围内
        self.assertFalse(form.is_valid())
        self.assertIn('orange', form.errors)

代码说明

  • setUp方法:提前创建所有测试需要的实例,避免每个测试重复造数据,提升测试效率
  • test_form_queryset_only_shows_unassigned_oranges:直接检查表单的queryset内容,确保你的过滤逻辑生效
  • test_form_valid_submission_assigns_orange_to_apple:端到端验证完整提交流程,包括关联后的状态变化
  • test_form_invalid_when_no_orange_selected:验证必填字段的基础校验逻辑
  • test_form_invalid_when_assigning_already_assigned_orange:额外测试后端防护,防止恶意提交已分配的Orange

这样写的测试用例就能全面覆盖你表单的核心逻辑啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:06:53