首页 > 解决方案 > Django单元测试:MultipleChoiceField依赖于setUp期间创建的对象

问题描述

我正在尝试测试一个表单,其中包含MultipleChoiceField来自数据库的内容。目前测试失败,因为通过的选择无效。原因是该字段似乎没有任何数据。

测试结果和调试打印语句

<QuerySet []>
System check identified no issues (0 silenced).
<QuerySet [<Subject: Subject object (1)>, <Subject: Subject object (2)>]>
<ul class="errorlist"><li>subjects<ul class="errorlist"><li>
Select a valid choice. Subject object (1) is not one of the available choices.</li></ul></li></ul>

代码

# TEST
def test_lecturer(self):
        print(Subject.objects.all())
        subjects = [self.subject, self.subject2]
        response = self.client.post(reverse('manager:register'),
                {'email' : self.lecturer_email, 
                'is_lecturer' : True,
                'subjects' : subjects })
        lecturer = UserProfile.objects.get(email=self.lecturer_email)
        self.assertEqual(lecturer.can_edit, subjects)

# FORM
class UserCsvForm(forms.Form):
    try:
        subjects = [(x,x.title) for x in Subject.objects.all()]
    except:
        subjects = []

    print(Subject.objects.all())
    ... OTHER FIELDS ...

    subjects = forms.MultipleChoiceField(choices=subjects, required=False)

似乎在设置测试之前调用了表单,但是不应该只在发送发布请求后生成表单吗?

标签: pythondjangounit-testing

解决方案


您的问题在于您为该subjects字段生成选择的方式。这些选项是在类级别生成的,这意味着它们是在加载您的应用程序时首次导入表单时生成的,并且在应用程序重新启动之前是“静态的”。

您应该使用 aModelMultipleChoiceField相反,将查询集传递给它,并且每次创建表单实例时都会执行此查询集。这将为您提供动态选择,当您向数据库添加/删除条目时这些选择将更新

class UserCsvForm(forms.Form):
    ...
    subjects = forms.ModelMultipleChoiceField(Subject.objects.all(), required=False)

推荐阅读