我一直在努力模拟表单类,以在基于类的视图中替换其实例。但是看起来像这样,因为该表单位于类属性中,所以它发生在之前,我用我的模拟替换了表单类。例子:
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
,并使用pdb重新定义了变量form
,这使我的测试通过了。
似乎由于某种原因,SomeViewClass
在开始修补SomeForm
之前已被[注册,实例化...]。有什么想法吗?
答案 0 :(得分:0)
问题是Django已经加载了视图,并且form
字段已经定义并指向SomeForm
production 类。
正如@DanielRoseman和@foxyblue在其注释中指出的那样,可以直接在类中修补字段。实际上是there was already an answer for that on SO。如所指出的,可以使用patch.object
to patch a member of a class(这是IMO,最好的解决方案,因为它更加明确,并且不太容易出现错字)
使用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
@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