Django Rest Framework - Как проверить ViewSet?
У меня возникли проблемы с тестированием 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)
Я пытаюсь реплицировать синтаксис здесь:
http://www.django-rest-framework.org/api-guide/testing#forcing-authentication
Но я думаю, что их вид AccountDetail отличается от моего ViewSet, поэтому я получаю эту ошибку из последней строки:
AttributeError: 'NoneType' object has no attributes 'items'
Есть ли здесь правильный синтаксис или я смешиваю понятия? Мои тесты APIClient работают, но я использую factory здесь, потому что в конце концов мне захочется добавить "request.user = some_user". Спасибо заранее!
О, и клиентский тест работает нормально:
def test_client_view(self):
response = APIClient().get(reverse('cat-detail', args=(cat.pk,)))
self.assertEqual(response.status_code, 200)
Ответы
Ответ 1
Я думаю, что нашел правильный синтаксис, но не уверен, что он обычный (новичок в 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)
Итак, теперь это проходит, и я могу назначить request.user, который позволяет мне настроить метод извлечения в CatViewSet, чтобы рассмотреть пользователя.
Ответ 2
У меня была такая же проблема, и я смог найти решение.
Взглянув на исходный код, похоже, что в представлении предполагается, что существует аргумент "действия", в котором есть элементы метода (так, dict).
https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/viewsets.py#L69
Вот откуда исходит ошибка. Вам нужно будет указать действия аргумента с помощью dict, содержащего разрешенные действия для этого вида, а затем вы сможете проверить правильность представления.
Общее отображение:
{
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy'
}
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)
EDIT: вам действительно нужно указать необходимые действия. Измененный код и комментарии, чтобы отразить это.
Ответ 3
Я думаю, это твоя последняя строка. Вы должны вызвать CatViewSet as_view(). Я бы пошел с:
response = view(request)
учитывая, что вы уже определили view = CatViewSet.as_view()
EDIT:
Можете ли вы показать свой views.py
? В частности, какой тип ViewSet
вы использовали? Я копаю код DRF, и похоже, что у вас могут не быть какие-либо действия, сопоставленные с вашим представлением ViewSet, который вызывает ошибку.
Ответ 4
Я нашел способ сделать это без необходимости вручную создавать правильный viewet и давать ему сопоставление действий:
from django.core.urlresolvers import reverse, resolve
...
url = reverse('cat-list')
req = factory.get(url)
view = resolve(url).func
response = view(req)
response.render()