Django Rest Framework的测试请求不能由自己的Request类解析

时间:2016-09-28 20:58:11

标签: python unit-testing django-rest-framework

我正在编写端点以使用Django Rest Framework 3接收和解析here。为了匹配有效负载规范,我正在编写有效负载请求工厂并测试它&#39} ; s生成有效请求。

然而,当尝试测试使用DRF的APIRequestFactory类生成的请求时,会出现问题。这是我能提出的最小的失败测试 - 问题是DRF Request生成的请求似乎无法通过DRF from rest_framework.request import Request from rest_framework.parsers import JSONParser from rest_framework.test import APIRequestFactory, APITestCase class TestRoundtrip(APITestCase): def test_round_trip(self): """ A DRF Request can be loaded into a DRF Request object """ request_factory = APIRequestFactory() request = request_factory.post( '/', data={'hello': 'world'}, format='json', ) result = Request(request, parsers=(JSONParser,)) self.assertEqual(result.data['hello'], 'world') 类解析。这是预期的行为吗?

E
======================================================================
ERROR: A DRF Request can be loaded into a DRF Request object
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/james/active/prlint/venv/lib/python3.4/site-packages/rest_framework/request.py", line 380, in __getattribute__
    return getattr(self._request, attr)
AttributeError: 'WSGIRequest' object has no attribute 'data'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/james/active/prlint/prlint/github/tests/test_payload_factories/test_roundtrip.py", line 22, in test_round_trip
    self.assertEqual(result.data['hello'], 'world')
  File "/home/james/active/prlint/venv/lib/python3.4/site-packages/rest_framework/request.py", line 382, in __getattribute__
    six.reraise(info[0], info[1], info[2].tb_next)
  File "/home/james/active/prlint/venv/lib/python3.4/site-packages/django/utils/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "/home/james/active/prlint/venv/lib/python3.4/site-packages/rest_framework/request.py", line 186, in data
    self._load_data_and_files()
  File "/home/james/active/prlint/venv/lib/python3.4/site-packages/rest_framework/request.py", line 246, in _load_data_and_files
    self._data, self._files = self._parse()
  File "/home/james/active/prlint/venv/lib/python3.4/site-packages/rest_framework/request.py", line 312, in _parse
    parsed = parser.parse(stream, media_type, self.parser_context)
  File "/home/james/active/prlint/venv/lib/python3.4/site-packages/rest_framework/parsers.py", line 64, in parse
    data = stream.read().decode(encoding)
AttributeError: 'str' object has no attribute 'read'

----------------------------------------------------------------------

堆栈跟踪是:

Request

我显然做了一些愚蠢的事情 - 我已经弄乱了编码...意识到我需要将解析器列表传递给UnsupportedMediaType以避免APIRequestFactory错误,现在我被困在这里。

我应该做些不同的事吗?也许避免使用X-GitHub-Event?或者以不同的方式测试我构建的GitHub请求?

更多信息

GitHub向具有def PayloadRequestFactory(): """ Build a Request, configure it to look like a webhook payload from GitHub. """ request_factory = APIRequestFactory() request = request_factory.post(url, data=PingPayloadFactory()) request.META['HTTP_X_GITHUB_EVENT'] = 'ping' return request 标头的已注册webhook发送请求,因此为了测试我的webhook DRF代码,我需要能够在测试时模拟此标头。

我成功的道路是构建自定义请求并使用工厂将负载加载到其中。这是我的工厂代码:

PayloadRequestFactory

问题已经出现,因为我想断言Request正在为各种传递的参数生成有效请求 - 所以我试图解析它们并断言它们的有效性但是DRF的{{1}类似乎无法实现这一点 - 因此我的问题是测试失败。

所以我真正的问题是 - 我应该如何测试PayloadRequestFactory是否产生了我需要的那种请求?

2 个答案:

答案 0 :(得分:1)

"哟dawg,我听说你喜欢Request,cos'你把一个请求放在一个请求中#34; XD

我这样做:

from rest_framework.test import APIClient

client = APIClient()
response = client.post('/', {'github': 'payload'}, format='json')
self.assertEqual(response.data, {'github': 'payload'})
# ...or assert something was called, etc.

希望这有帮助

答案 1 :(得分:1)

查看tests for APIRequestFactory in DRFstub views 创建然后运行该视图 - 检查输出以获得预期结果。 因此,合理但稍长的解决方案是将此策略复制到 在此之前断言PayloadRequestFactory正在构建有效请求 指向一个完整的视图。

上述测试成为:

from django.conf.urls import url
from django.test import TestCase, override_settings
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.test import APIRequestFactory


@api_view(['POST'])
def view(request):
    """
    Testing stub view to return Request's data and GitHub event header.
    """
    return Response({
        'header_github_event': request.META.get('HTTP_X_GITHUB_EVENT', ''),
        'request_data': request.data,
    })


urlpatterns = [
    url(r'^view/$', view),
]


@override_settings(ROOT_URLCONF='github.tests.test_payload_factories.test_roundtrip')
class TestRoundtrip(TestCase):

    def test_round_trip(self):
        """
        A DRF Request can be loaded via stub view
        """
        request_factory = APIRequestFactory()
        request = request_factory.post(
            '/view/',
            data={'hello': 'world'},
            format='json',
        )

        result = view(request)

        self.assertEqual(result.data['request_data'], {'hello': 'world'})
        self.assertEqual(result.data['header_github_event'], '')

哪些通过:D