在基于类的视图中模拟表单不使用MagicMock [英] Mocking form in class based view not using the MagicMock

查看:49
本文介绍了在基于类的视图中模拟表单不使用MagicMock的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在努力模拟表单类,以在基于类的视图中替换其实例.但是看起来像这样,因为该表单位于类属性中,所以它发生在之前,我用我的模拟替换了表单类.恰当的例子:

I've been fighting with mocking a form class to replace an instance of it in a class-based view. But it looks like that because the form is in a class attribute, it happens before I replace the form class with my mock. Case in point:

app/views.py

from app.forms import SomeForm  # For some reason, this _is_ my mock...

class SomeViewClass(View):
    form = SomeForm  # ... while this is the _real_ SomeForm

    def post(self, request):
        form = self.form(request.POST, request.FILES)

        # Hacked around with pdb here
        # (Pdb) self.form = SomeForm <-- Force the mock into the object
        # (Pdb) form = self.form(request.POST, request.FILES)
        # (Pdb) form.is_valid() is now True
        # (Pdb) continue <--- Test finishes, and asserts are OK.

        if form.is_valid():  # This fails, as I'm running the real code
            # code, code, code

app/tests/test_views.py

from mock import MagicMock, patch

from django.tests import Client, TestCase


@patch('app.views.SomeForm')
    def test_post_valid_form_should_pass(self, mocked_form_class):
        """ Replacing SomeForm in SomeViewClass to pas the is_valid test
        """
        form_instance = MagicMock(spec=SomeForm())
        form_instance.is_valid.return_value = True
        mocked_form_class.return_value = form_instance

        self.client.login(**self.credentials)
        # code, code, code

正如您在 app/views.py 中插入的注释中所看到的那样,我强行重新加载了 self.form 并重新定义了变量 form 使用pdb,这使我的测试通过了.

As you can see in the inserted comments in app/views.py, I forcefully reloaded self.form and redefined the variable form using pdb, which made my test pass.

由于某些原因,在我开始修补 SomeForm 之前, SomeViewClass 是[已注册,实例化...].有什么想法吗?

It seems that for some reason, the SomeViewClass is [registered,instanciated,...] before I start patching SomeForm. Any ideas on that?

推荐答案

问题是Django已经加载了视图,并且 form 字段已经定义并指向 SomeForm production 类.

The problem is that the view is already loaded by Django and the form field is already defined and pointing to the SomeForm production class.

正如@DanielRoseman和@foxyblue在其注释中指出的那样,可以直接在类中修补字段.实际上,在SO上已经有一个答案.如所指出的,可以使用 patch.object

As @DanielRoseman and @foxyblue pointed out in their comments, it is possible to patch directly a field in a class. And actually there was already an answer for that on SO. As pointed out, it is possible to use patch.object to patch a member of a class (which is, IMO, the best solution, as it's more explicit, and less prone to typos)

具有补丁

With patch

@patch('app.views.SomeView.form', autospec=SomeForm)
    def test_post_valid_form_should_pass(self, mocked_form_class):
        """ Replacing SomeForm in SomeViewClass.form to pass the is_valid test """
        mocked_form_class.is_valid.return_value = True

        self.client.login(**self.credentials)
        # code, code, code

使用 patch.object

With patch.object

@patch.object(SomeView, 'form', autospec=SomeForm)
    def test_post_valid_form_should_pass(self, mocked_form_class):
        """ Replacing SomeForm in SomeViewClass.form to pass the is_valid test """
        mocked_form_class.is_valid.return_value = True

        self.client.login(**self.credentials)
        # code, code, code

这篇关于在基于类的视图中模拟表单不使用MagicMock的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆