问题描述
我一直在努力模拟表单类,以在基于类的视图中替换其实例.但是看起来像这样,因为该表单位于类属性中,所以它发生在之前,我用我的模拟替换了表单类.恰当的例子:
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
修补一个类的成员(这是IMO,这是最好的解决方案,因为它更明确,并且更不会出现错字)
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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!