简体   繁体   中英

Django Unit Testing : MultipleChoiceField dependent on objects created during setUp

I'm trying to test a form which has a MultipleChoiceField which is populated with content from the database. Currently the test is failing, because the choices passed are invalid. The reason being that the field doesn't seem to have any data on it.

TEST RESULTS & DEBUG PRINT STATEMENTS

<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>

CODE

# 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)

It seems like the form is being called before the test is setup, but shouldn't the form only be generated once the post request is sent?

Your issue is with the way you are generating the choices for the subjects field. The choices are being generated at the class level which means that they are generated when the form is first imported on load of your app and are "static" until the app is restarted.

You should use a ModelMultipleChoiceField instead, you pass a queryset to it and this queryset is executed every time a form instance is created. This will give you dynamic choices that will update when you add/remove entries to the DB

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM