Django 1.9.2 测试客户端问题

Posted

技术标签:

【中文标题】Django 1.9.2 测试客户端问题【英文标题】:Django 1.9.2 test Client issue 【发布时间】:2016-06-10 05:05:10 【问题描述】:

我正在使用Django==1.9.2djangorestframework==3.3.2django.test.Client 进行一些测试。问题是,当我执行测试时,我遇到了这个错误:

ERROR: test_view (main.tests.test_http.TestMainViewSet)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/vladir/work/all/project-django1.9/saxo-publish/publish/main/tests/test_http.py", line 111, in test_view
    content_type='application/json'
  File "/home/vladir/work/all/project-django1.9/venv/local/lib/python2.7/site-packages/django/test/client.py", line 515, in post
    secure=secure, **extra)
  File "/home/vladir/work/all/project-django1.9/venv/local/lib/python2.7/site-packages/django/test/client.py", line 314, in post
    secure=secure, **extra)
  File "/home/vladir/work/all/project-django1.9/venv/local/lib/python2.7/site-packages/django/test/client.py", line 380, in generic
    return self.request(**r)
  File "/home/vladir/work/all/project-django1.9/venv/local/lib/python2.7/site-packages/django/test/client.py", line 449, in request
    response = self.handler(environ)
  File "/home/vladir/work/all/project-django1.9/venv/local/lib/python2.7/site-packages/django/test/client.py", line 123, in __call__
    response = self.get_response(request)
  File "/home/vladir/work/all/project-django1.9/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 245, in get_response
    response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
  File "/home/vladir/work/all/project-django1.9/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 296, in handle_uncaught_exception
    return callback(request, **param_dict)
  File "/home/vladir/work/all/project-django1.9/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 166, in _wrapped_view
    return middleware.process_response(request, response)
  File "/home/vladir/work/all/project-django1.9/venv/local/lib/python2.7/site-packages/django/middleware/csrf.py", line 230, in process_response
    request.META["CSRF_COOKIE"],
KeyError: u'CSRF_COOKIE'

我的测试代码如下所示:

import json

from django.test import Client
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User


class TestMainViewSet(TestCase):

    def setUp(self):
        self.client = Client(
            HTTP_HOST='example.com' # I have also tried removing this
        )
        self.create_read_url = reverse('books-list')
        User.objects.create_user(
            username="username",
            email="username@zunzun.se",
            password="123"
        ) 

    def test_create(self):
        self.client.login(username='username', password="123")
        # In this case I'm doing a POST, but it is the same with a GET
        response = self.client.post(
            self.create_read_url,
            data=json.dumps('title': "Create"), # I have also tried without the json.dumps
            content_type='application/json'
        )

        data = json.loads(response.content)
        print data

        self.assertEqual(response.status_code, 201)
        self.assertEquals(data['title'], "Create")

我的view 代码是:

from django.contrib.auth.mixins import LoginRequiredMixin

from rest_framework import viewsets

from .serialiazers import (
    BookSerializerRead,
    BookSerializerWrite,
)

class MainViewSet(LoginRequiredMixin, viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class_read = BookSerializerRead
    serializer_class_write = BookSerializerWrite

urls.py

from rest_framework import routers

router = routers.DefaultRouter()
router.register(r'books', MainViewSet, 'books')


urlpatterns = [
    url(r'^api/', include(router.urls)),
]

根据Django doc 关于它,我不需要任何额外的东西来避免CSRF checks, 因为正如那里的文字所说:“默认情况下,测试客户端将禁用您的站点执行的任何 CSRF 检查。”,我也知道默认情况下enforce_csrf_checks=FalseClient

我发现了一个细节,如果我以这种方式创建客户端实例self.client = Client(HTTP_HOST='example.com', CSRF_COOKIE='xxxxxx') 那么它可以工作,但就是这样 实际需要?这不是文档所说的,所以我想我做错了什么。有人可以帮我吗?我将不胜感激任何帮助。 提前致谢

【问题讨论】:

DRF 提供了不同的测试机制,您可能想尝试一下:django-rest-framework.org/api-guide/testing 感谢@TomCarrick 的建议,很有用,之前没用过。我肯定会测试这个。我的主要问题是从Django 1.8.4Django 1.9.2 的变化是什么破坏了这个?从我的角度来看,它与Django 本身有关,最后它是jsonDjango Rest Framework 端点的请求,我认为它应该有效:(。再次感谢队友。跨度> 【参考方案1】:

尝试使用 DRF 的 APITestCase 作为测试用例的基类:

from rest_framework.testing import APITestCase

class TestMainViewSet(APITestCase):
    ...

【讨论】:

以上是关于Django 1.9.2 测试客户端问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 django 测试客户端发送 JSON

如何在 Django 测试客户端中保持 POST 参数的顺序?

如何使用 django-rest-framework 测试客户端测试二进制文件上传?

Django 测试客户端在访问 url 时得到 301 重定向

Django 测试客户端不会自动序列化工厂

Django 测试客户端方法覆盖标头