django-crispy-form:单元测试因helper对象的TypeError失败

3 投票
1 回答
691 浏览
提问于 2025-04-18 14:21

这段内容是关于在使用django-crispy-form创建表单时,进行单元测试遇到的问题。作者提到,他们在测试时遇到了一个错误:

类型错误:提供给{% crispy %}标签的助手对象必须是crispy.helper.FormHelper对象。

这里提到的表单在(myapp/forms.py)文件中:

class MyBaseForm(forms.models.ModelForm):

    def __init__(self, *args, **kwargs):
        super(MyBaseForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_id = 'id-myForm'
        self.helper.form_method = 'POST'
        self.helper.form_action = ''
        self.helper.add_input(Submit('submit', 'Create'))

    class Meta:
        model = MyModel
        # [...]

class MyNewForm(MyBaseForm):

    def save(self):
        return MyModel.create_new(data=self.cleaned_data['data'])

视图代码在(myapp/views.py)文件中:

@login_required
def event_new(request):
    if request.method == 'POST':
        form = MyNewForm(data=request.POST)
        if form.is_valid():
            event = form.save()
            return redirect(event)
    else:
        form = MyNewForm()
return render(request, 'event_new.html', {'form': form})

测试代码在:

@patch('myapp.views.MyNewForm')
class MyNewViewUnitTest(TestCase):

    def setUp(self):
        self.t = unittest.TestCase()
        self.t.request = HttpRequest()
        self.t.request.POST['data'] = 'data'
        self.t.request.user = Mock()

    def test_passes_POST_data_to_Form(self, mockMyNewForm):
        event_new(self.t.request)
        mockMyNewForm.assert_called_once_with(data=self.t.request.POST)

作者在问,是否需要模拟助手对象?如果需要的话,应该怎么做?非常感谢!

1 个回答

2

虽然我来得有点晚,但今天遇到了这个问题。你需要为你的模拟类指定一个助手,指定为 FormHelper,这样在 crispy 模板中使用的 "isinstance" 调用才能通过。最简单的方法是为 crispy 表单创建一个 MagicMock 的子类:

class MockCrispyForm(MagicMock):
    helper = MagicMock(spec=FormHelper)
    helper.template = False  # necessary for templates to render
    def is_valid(self):
        return True  # optional if you want form to validate

@patch('myapp.views.MyNewForm', MockCrispyForm())
class MyNewViewUnitTest(TestCase):
    def setUp(self):
        self.t = unittest.TestCase()
        self.t.request = HttpRequest()
        self.t.request.POST['data'] = 'data'
        self.t.request.user = Mock()

    def test_passes_POST_data_to_Form(self):
        event_new(self.t.request)
        myapp.views.MyNewForm.assert_called_once_with(
            data=self.t.request.POST
        )

撰写回答