How can I write a unittest to check that a django model form is valid?

馋奶兔 提交于 2020-01-06 11:51:39

问题


I am trying to test that a model form is valid.

In the test function, I create the two models that feature in my custom form. I add the data to fill the form's required fields.

When I run the tests and call is_valid() on the form, the test fails and the form gives the error that the option that I have added is not one of the available choices. This suggests to me that I have incorrectly added the Option instance to the form or to the test. I am unsure how.

How can I make the model form valid for the test?

tests.py

    def test_valid_data(self):
        question_1 = Question(
            question_text='What is the width of the telephone?',
            date_published=timezone.now(),
            collection=Collection.objects.create()
        )
        question_1.save()
        option_1 = question_1.options.create(
            question=question_1,
            option_text='Five centimetres'
        )
        option_1.save()
        data = {'question_text': question_1.question_text, 'selected_option': option_1.option_text,}
        form = QuestionForm(data=data)
        print(form)
        self.assertTrue(form.is_valid())

forms.py

class QuestionForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(QuestionForm, self).__init__(*args, **kwargs)
        self.fields['selected_option'] = forms.ChoiceField(
            choices=[
                (f'{option.pk}', f'{option}')
                for option in Option.objects.filter(question_id=self.instance.pk)
            ],
            widget=RadioSelect,
            required=True,
            error_messages={
                'required': 'The question form lacks a selected_option'
            }

        )

    class Meta:
        model = Question
        fields = ('question_text',)
        labels = {
            'question_text': ''
        }
        widgets = {
            'question_text': forms.Textarea(attrs={'cols': '40', 'rows': '2'})
        }

models.py

class Question(models.Model):
    question_text = models.CharField(max_length=400)
    collection = models.ForeignKey(Collection, on_delete=models.PROTECT, default=None)
    date_published = models.DateTimeField('date published')

    def __str__(self) -> str:
        return self.question_text


class Option(models.Model):
    option_text = models.CharField(max_length=400)
    question = models.ForeignKey(Question, on_delete=models.CASCADE)

    class Meta:
        default_related_name = 'options'

    def __str__(self) -> str:
        return self.option_text

Expected: is_valid() -> True

Actual:is_valid() -> False


回答1:


The issue is caused by the way that you have defined choices in QuestionForm.__init__:

choices=[
    (f'{option.pk}', f'{option}')
    for option in Option.objects.filter(question_id=self.instance.pk)
],

You have created choices based on the pk of the Question instance related with the QuestionForm you initiate.

In your test (and also in the admin), the form is not bound to any instance of Question when you initiate the form by entering form = QuestionForm(data=data).

Consequently, the query Option.objects.filter(question_id=self.instance.pk) returns None because self.instance.pk is None.

Therefore, you receive the error before saving the QuestionForm because choices = []

The query would return results if you pressed the "Save" button or if you do a form.save().



来源:https://stackoverflow.com/questions/56061676/how-can-i-write-a-unittest-to-check-that-a-django-model-form-is-valid

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!