代码之家  ›  专栏  ›  技术社区  ›  fabio

ValueError:无法使用Mock()分配

  •  0
  • fabio  · 技术社区  · 7 年前

    我正在学习如何在django中使用Mock进行测试(2.0.6<=它可以带来不同),但我被一个教程困住了。

    这是我的 test_views.py :

    User = get_user_model() #I use this in other tests, I hope it don't interfere
    
    @patch('lists.views.NewListForm')
    class NewListViewUnitTest(unittest.TestCase):
    
        def setUp(self):
            self.request = HttpRequest()
            self.request.POST['text'] = 'new list item'
            self.request.user = Mock()
    
        def test_passes_POST_data_to_NewListForm(self, mockNewListForm):
            print('self.request', self.request.user)
            new_list2(self.request)
            mockNewListForm.assert_called_once_with(data=self.request.POST)
    
    [...]
    

    下面是我在测试中的错误:

    self.request <Mock name='mock()' id='80288792'> #print result
    E
    ======================================================================
    ERROR: test_passes_POST_data_to_NewListForm (lists.tests.test_views.NewListViewU
    nitTest)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "d:\python\Lib\unittest\mock.py", line 1179, in patched
        return func(*args, **keywargs)
      File "D:\progetti\superlists\lists\tests\test_views.py", line 149, in test_pas
    ses_POST_data_to_NewListForm
        new_list2(self.request)
      File "D:\progetti\superlists\lists\views.py", line 42, in new_list2
        list_.owner = request.user
      File "C:\Users\fabio\.virtualenvs\superlist\lib\site-packages\django\db\models
    \fields\related_descriptors.py", line 197, in __set__
        self.field.remote_field.model._meta.object_name,
    ValueError: Cannot assign "<Mock name='mock()' id='80288792'>": "List.owner" must be a "User" instance.
    

    所以,它看起来好像不认识 self.request.user = Mock() 就像一个用户实例。

    关于 test_view :

    1) 那个 print 命令

    2) 那个 User = get_user_model() 变量 get_user_model() 来自 django.contrib.auth .我想这不会妨碍你。

    为了完整性,我添加了一些代码,如果需要,可以要求更多。

    我的观点。py:

    def new_list2(request):
        form = NewListForm(data=request.POST)
        if form.is_valid():
            list_ = List()
            if request.user.is_authenticated:
                list_.owner = request.user
            list_.save()
            form.save(owner=request.user)
            return redirect(list_)
        return render(request, 'home.html', {'form': form})
    

    我的 forms.py :

    class ItemForm(forms.models.ModelForm):
    
        class Meta:
            model = Item
            fields = ('text',)
            widgets = {
                'text': forms.fields.TextInput(attrs={
                    'placeholder': 'Enter a to-do item',
                    'class': 'form-control input-lg',
                }),
            }
            error_messages = {
                'text': {'required': EMPTY_ITEM_ERROR}
            }
    
        def save(self, for_list):
            self.instance.list = for_list
            return super().save()
    
    class NewListForm(ItemForm):
    
        def save(self, owner):
            if owner.is_authenticated:
                return List.create_new(first_item_text=self.cleaned_data['text'], 
                    owner=owner)
            else:
                return List.create_new(first_item_text=self.cleaned_data['text'])
    

    我的 models.py :

    class List(models.Model):
        owner = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, 
            on_delete=models.PROTECT)
    
        def get_absolute_url(self):
            return reverse('view_list', args=[self.id])
    
        @staticmethod
        def create_new(first_item_text, owner=None):
            list_ = List.objects.create(owner=owner)
            Item.objects.create(text=first_item_text, list=list_)
            return list_
    
        @property
        def name(self):
            return self.item_set.first().text
    
        #def __str__(self):
        #    return self.item_set.first().text
    
    class Item(models.Model):
        text = models.TextField(default='')
        list = models.ForeignKey(List, default=None, on_delete=models.PROTECT)
    
        class Meta:
            ordering = ('id',)
            unique_together = ('list', 'text')
    
        def __str__(self):
            return self.text
    

    请,任何帮助都将不胜感激

    0 回复  |  直到 7 年前