Django Rest Framework - 如何测试ViewSet?

WBC*_*WBC 24 python django django-rest-framework

我在测试ViewSet时遇到问题:

class ViewSetTest(TestCase):
    def test_view_set(self):
        factory = APIRequestFactory()
        view = CatViewSet.as_view()
        cat = Cat(name="bob")
        cat.save()

        request = factory.get(reverse('cat-detail', args=(cat.pk,)))
        response = view(request)
Run Code Online (Sandbox Code Playgroud)

我正在尝试复制语法:

http://www.django-rest-framework.org/api-guide/testing#forcing-authentication

但我认为他们的AccountDetail视图与我的ViewSet不同,所以我从最后一行收到此错误:

AttributeError: 'NoneType' object has no attributes 'items'
Run Code Online (Sandbox Code Playgroud)

这里有正确的语法还是我混淆概念?我的APIClient测试工作,但我在这里使用工厂,因为我最终想添加"request.user = some_user".提前致谢!

哦,客户端测试工作正常:

def test_client_view(self):
    response = APIClient().get(reverse('cat-detail', args=(cat.pk,)))
    self.assertEqual(response.status_code, 200)
Run Code Online (Sandbox Code Playgroud)

WBC*_*WBC 19

我想我找到了正确的语法,但不确定它是否是传统的(对Django来说还是新的):

def test_view_set(self):
    request = APIRequestFactory().get("")
    cat_detail = CatViewSet.as_view({'get': 'retrieve'})
    cat = Cat.objects.create(name="bob")
    response = cat_detail(request, pk=cat.pk)
    self.assertEqual(response.status_code, 200)
Run Code Online (Sandbox Code Playgroud)

所以现在这个传递了,我可以分配request.user,它允许我自定义CatViewSet下的检索方法来考虑用户.


chr*_*ans 10

我遇到了同样的问题,并且能够找到解决方案.

查看源代码,看起来视图期望有一个参数'actions',它有一个方法项(所以,一个字典).

https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/viewsets.py#L69

这就是你得到的错误来自哪里.您必须使用包含该视图集的允许操作的dict指定参数操作,然后您才能正确测试视图集.

一般映射如下:

{
    'get': 'retrieve',
    'put': 'update',
    'patch': 'partial_update',
    'delete': 'destroy'
}
Run Code Online (Sandbox Code Playgroud)

http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers

在你的情况下,你需要{'get':'retrieve'}如下所示:

class ViewSetTest(TestCase):
    def test_view_set(self):
        factory = APIRequestFactory()
        view = CatViewSet.as_view(actions={'get': 'retrieve'}) # <-- Changed line
        cat = Cat(name="bob")
        cat.save()

        request = factory.get(reverse('cat-detail', args=(cat.pk,)))
        response = view(request)
Run Code Online (Sandbox Code Playgroud)

编辑:您实际上需要指定所需的操作.更改了代码和注释以反映这一点.


Tim*_*ter 8

我找到了一种方法来做到这一点,而无需手动创建正确的视图集并给它一个动作映射:

from django.core.urlresolvers import reverse, resolve
...
url = reverse('cat-list')
req = factory.get(url)
view = resolve(url).func
response = view(req)
response.render()
Run Code Online (Sandbox Code Playgroud)


Ale*_*lex 4

我想这是你的最后一行。您需要调用 CatViewSet as_view()。我会选择:

response = view(request)
Run Code Online (Sandbox Code Playgroud)

鉴于您已经定义了view = CatViewSet.as_view()

编辑:

你能展示一下你的views.py吗?ViewSet具体来说,你用的是什么类型的?我正在深入研究 DRF 代码,看起来您可能没有任何操作映射到您的 ViewSet,这会触发错误。