python – 具有模拟数据的ModelChoiceField的UnitTest ModelForm
我一直在尝试为我的ModelForm编写单元测试,它有一个ModelChoiceField.我正在使用模拟数据创建Form实例.
这是我的模特: # models.py class Menu(models.Model): dish = models.ForeignKey(Dish,default=None) price = models.DecimalField(max_digits=7,decimal_places=2) # forms.py class MenuForm(forms.ModelForm): class Meta: model = Menu fields = ('dish','price',) def clean(self): cleaned_data = super(MenuForm,self).clean() price = cleaned_data.get('price',None) dish = cleaned_data.get('dish',None) # Some validation below if price < 70: self.add_error('price','Min price threshold') return cleaned_data 这是我的测试用例: class MenuFormTest(TestCase): def test_price_threshold(self): mock_dish = mock.Mock(spec=Dish) form_data = { 'dish': mock_dish,'price': 80,} form = forms.MenuForm(data=form_data) self.assertTrue(form.is_valid()) 此操作失败,并显示以下错误: <ul class="errorlist"><li>dish<ul class="errorlist"><li>Select a valid choice. That choice is not one of the available choices.</li></ul></li></ul> 如何避免抛出该错误. form.is_valid()应该是True.有没有办法可以修补ModelChoiceField的查询集?我试着修补form的dish field clean()方法,如下所示: form = forms.MenuForm(data=form_data) dish_clean_patcher = mock.patch.object(form.fields['dish'],'clean') dish_clean_patch = dish_clean_patcher.start() dish_clean_patch.return_value = mock_dish self.assertTrue(form.is_valid()) 然后看起来,它在将表单数据保存到_post_clean()方法中的模型实例时失败了.这是追溯: Traceback (most recent call last): File "/home/vagrant/venv/local/lib/python2.7/site-packages/mock/mock.py",line 1305,in patched return func(*args,**keywargs) File "/vagrant/myapp/tests/test_forms.py",line 51,in test_price_threshold self.assertFalse(form.is_valid()) File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/forms/forms.py",line 185,in is_valid return self.is_bound and not self.errors File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/forms/forms.py",line 177,in errors self.full_clean() File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/forms/forms.py",line 396,in full_clean self._post_clean() File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/forms/models.py",line 427,in _post_clean self.instance = construct_instance(self,self.instance,opts.fields,construct_instance_exclude) File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/forms/models.py",line 62,in construct_instance f.save_form_data(instance,cleaned_data[f.name]) File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py",line 874,in save_form_data setattr(instance,self.name,data) File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/db/models/fields/related.py",line 632,in __set__ instance._state.db = router.db_for_write(instance.__class__,instance=value) File "/home/vagrant/venv/local/lib/python2.7/site-packages/django/db/utils.py",line 300,in _route_db if instance is not None and instance._state.db: File "/home/vagrant/venv/local/lib/python2.7/site-packages/mock/mock.py",line 716,in __getattr__ raise AttributeError("Mock object has no attribute %r" % name) AttributeError: Mock object has no attribute '_state' 我该如何避免这一部分?我根本不想查看instance._state.db. 我正确测试表格吗?或者我应该而不是调用form.is_valid(),只需调用form.clean()方法,完全修补super(MenuForm,self).clean()方法,并检查form.errors? 解决方法
我会说调用form.is_valid()是测试表单的好方法.我不确定嘲笑模型.
Internally the form is calling You would need to mock the 或者,在测试中创建一个Dish并让Django的内部继续做他们正在做的事情会更简单. class MenuFormTest(TestCase): def test_price_threshold(self): dish = Dish.objects.create( # my values here ) form_data = { 'dish': dish.id,} form = MenuForm(data=form_data) self.assertTrue(form.is_valid()) 如果您真的没有使用Django的测试数据库,那么一种策略可能是模拟MenuForm.clean和MenuForm._post_clean: class MenuFormTest(TestCase): def test_price_threshold(self): mock_dish = mock.Mock(spec=Dish) form_data = { 'dish': 1,} form = MenuForm(data=form_data) form.fields['dish'].clean = lambda _: mock_dish form._post_clean = lambda : None self.assertTrue(form.is_valid()) 如果你打算这样做,你需要问问自己你的目标是什么. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |