Python Django Rest框架-如何测试ViewSet?
我在测试视图集时遇到问题:Python Django Rest框架-如何测试ViewSet?,python,django,django-rest-framework,Python,Django,Django Rest Framework,我在测试视图集时遇到问题: 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', ar
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)
我尝试在这里复制语法:
但我认为他们的AccountDetail视图与我的ViewSet不同,因此我从最后一行得到了这个错误:
AttributeError: 'NoneType' object has no attributes 'items'
这里有正确的语法吗?还是我混淆了概念?我的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)
我想这是你的最后一行了。您需要将CatViewSet调用为_view()。我同意:
response = view(request)
假设您已经定义了view=CatViewSet.as\u view()
编辑:
您可以显示您的
视图.py
?具体来说,您使用了什么类型的ViewSet
?我正在深入研究DRF代码,看起来您可能没有任何操作映射到视图集,这会触发错误。我想我找到了正确的语法,但不确定它是否是常规的(对Django来说还是新的):
所以现在我可以指定Revest.USER,它允许我在CabVIEW下自定义检索方法来考虑用户。
< P>我有同样的问题,并且能够找到解决方案。 查看源代码,看起来视图希望有一个参数“actions”,该参数包含一个方法项(因此,dict) 这就是你得到的错误的来源。必须使用包含该视图集允许的操作的dict指定参数操作,然后才能正确测试视图集 一般映射如下:{
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy'
}
在您的情况下,您需要{'get':'retrieve'}
像这样:
class ViewSetTest(TestCase):
def测试视图设置(自):
factory=APIRequestFactory()
view=CatViewSet.as_view(actions={'get':'retrieve'})#我找到了一种方法,无需手动创建正确的视图集并为其提供操作映射:
from django.core.urlresolvers import reverse, resolve
...
url = reverse('cat-list')
req = factory.get(url)
view = resolve(url).func
response = view(req)
response.render()
我需要通过强制身份验证来实现这一点,最终实现了这一点,以下是我的测试用例:
from django.test import TestCase
from rest_framework.test import APIRequestFactory
from django.db.models.query import QuerySet
from rest_framework.test import force_authenticate
from django.contrib.auth.models import User
from config_app.models import Config
from config_app.apps import ConfigAppConfig
from config_app.views import ConfigViewSet
class ViewsTestCase(TestCase):
def setUp(self):
# Create a test instance
self.config = Config.objects.create(
ads='{"frequency": 1, "site_id": 1, "network_id": 1}',
keys={}, methods={}, sections=[], web_app='{"image": 1, "label": 1, "url": 1}',
subscriptions=[], name='test name', build='test build', version='1.0test', device='desktop',
platform='android', client_id=None)
# Create auth user for views using api request factory
self.username = 'config_tester'
self.password = 'goldenstandard'
self.user = User.objects.create_superuser(self.username, 'test@example.com', self.password)
def tearDown(self):
pass
@classmethod
def setup_class(cls):
"""setup_class() before any methods in this class"""
pass
@classmethod
def teardown_class(cls):
"""teardown_class() after any methods in this class"""
pass
def shortDescription(self):
return None
def test_view_set1(self):
"""
No auth example
"""
api_request = APIRequestFactory().get("")
detail_view = ConfigViewSet.as_view({'get': 'retrieve'})
response = detail_view(api_request, pk=self.config.pk)
self.assertEqual(response.status_code, 401)
def test_view_set2(self):
"""
Auth using force_authenticate
"""
factory = APIRequestFactory()
user = User.objects.get(username=self.username)
detail_view = ConfigViewSet.as_view({'get': 'retrieve'})
# Make an authenticated request to the view...
api_request = factory.get('')
force_authenticate(api_request, user=user)
response = detail_view(api_request, pk=self.config.pk)
self.assertEqual(response.status_code, 200)
我在django nose test runner中使用了这个,它似乎工作得很好。希望它能帮助那些在视图集上启用了auth的人。最后一行,我可以在它之前转到调试器,所有内容都已定义,但我认为将请求传递到视图集中可能有什么特别之处?请尝试在最后一行传递pk
。查看同一页面上的呈现响应示例。第三行:response=view(request,pk='4')
hmm我试着把它传进来,对于view(request,pk=cat.pk)
和view(request,cat.pk)
你能发布你的url.py
和views.py
文件吗?此外,您可以尝试将第二行更改为最后一行,以使用硬编码路径,以确保在使用reverse之前可以正常工作。根据他们的文档,我试图让force auth正常工作,但它似乎不起作用。我不使用drf本机身份验证令牌,但我自己的jwt令牌,因此无法通过APIRequestFactory运行。
from django.core.urlresolvers import reverse, resolve
...
url = reverse('cat-list')
req = factory.get(url)
view = resolve(url).func
response = view(req)
response.render()
from django.test import TestCase
from rest_framework.test import APIRequestFactory
from django.db.models.query import QuerySet
from rest_framework.test import force_authenticate
from django.contrib.auth.models import User
from config_app.models import Config
from config_app.apps import ConfigAppConfig
from config_app.views import ConfigViewSet
class ViewsTestCase(TestCase):
def setUp(self):
# Create a test instance
self.config = Config.objects.create(
ads='{"frequency": 1, "site_id": 1, "network_id": 1}',
keys={}, methods={}, sections=[], web_app='{"image": 1, "label": 1, "url": 1}',
subscriptions=[], name='test name', build='test build', version='1.0test', device='desktop',
platform='android', client_id=None)
# Create auth user for views using api request factory
self.username = 'config_tester'
self.password = 'goldenstandard'
self.user = User.objects.create_superuser(self.username, 'test@example.com', self.password)
def tearDown(self):
pass
@classmethod
def setup_class(cls):
"""setup_class() before any methods in this class"""
pass
@classmethod
def teardown_class(cls):
"""teardown_class() after any methods in this class"""
pass
def shortDescription(self):
return None
def test_view_set1(self):
"""
No auth example
"""
api_request = APIRequestFactory().get("")
detail_view = ConfigViewSet.as_view({'get': 'retrieve'})
response = detail_view(api_request, pk=self.config.pk)
self.assertEqual(response.status_code, 401)
def test_view_set2(self):
"""
Auth using force_authenticate
"""
factory = APIRequestFactory()
user = User.objects.get(username=self.username)
detail_view = ConfigViewSet.as_view({'get': 'retrieve'})
# Make an authenticated request to the view...
api_request = factory.get('')
force_authenticate(api_request, user=user)
response = detail_view(api_request, pk=self.config.pk)
self.assertEqual(response.status_code, 200)