2

我有一个测试视图:

@api_view(['POST'])
@permission_classes([AllowAny])
@authentication_classes([])
def test_view(request):
    return Response(request.data)

它注册于urls.py

urlpatterns = [
    path('api/test/', test_view)
]

当我尝试[{"a": 1}, {"a": 2}]通过 REST Frameworks UI 手动发布时,一切正常。

但是,如果我为它编写测试,则会发生意外错误。这是测试

from rest_framework.test import APITestCase

class ViewTest(APITestCase):
    def test_it(self):
        response = self.client.post('/api/test/', [{"a": 1}, {"a": 2}])
        print(response)

这会产生以下错误:

Traceback (most recent call last):
  File "C:\development\HeedView\backend\clients\api\tests.py", line 13, in test_it
    response = self.client.post('/api/test/', [{"a":1}, {"a": 2}])
  File "C:\development\HeedView\venv\lib\site-packages\rest_framework\test.py", line 300, in post
    path, data=data, format=format, content_type=content_type, **extra)
  File "C:\development\HeedView\venv\lib\site-packages\rest_framework\test.py", line 212, in post
    data, content_type = self._encode_data(data, format, content_type)
  File "C:\development\HeedView\venv\lib\site-packages\rest_framework\test.py", line 184, in _encode_data
    ret = renderer.render(data)
  File "C:\development\HeedView\venv\lib\site-packages\rest_framework\renderers.py", line 921, in render
    return encode_multipart(self.BOUNDARY, data)
  File "C:\development\HeedView\venv\lib\site-packages\django\test\client.py", line 194, in encode_multipart
    for (key, value) in data.items():
AttributeError: 'list' object has no attribute 'items'

如何解释这种行为?

4

2 回答 2

2

要传递 json 数据,您需要添加format='json'. 该测试有效:

from rest_framework.test import APITestCase

class ViewTest(APITestCase):
    def test_it(self):
        response = self.client.post('/api/test/', [{"a": "1"}, {"a": 2}], format='json')
        print(response.json())

或者,如果您将默认格式设置settings.py

REST_FRAMEWORK = {
    ...
    'TEST_REQUEST_DEFAULT_FORMAT': 'json'
}

如果未指定格式:

Rest Framework APIClient扩展了 Django 现有的Client 类。Client.post的文档解释说:

数据字典中的键值对用于提交 POST 数据。例如:

...client.post('/login/', {'name': 'fred', 'passwd': 'secret'})

... [测试] 这个 POST 数据:

name=fred&passwd=secret

您的原始测试返回错误,因为如果未指定格式,则 Django 需要字典,而不是列表。

于 2019-10-06T21:23:09.023 回答
1

这是一个可行的测试:

from rest_framework.test import APITestCase

class ViewTest(APITestCase):
    def test_it(self):
        response = self.client.post('/api/test/', json.dumps([{"a": "1"}, {"a": 2}]),
                                    content_type='application/json')
        print(response.json())

但是,我仍然不明白,为什么我必须使用json.dumps(即以字符串形式提供数据)并明确指定内容类型。dict请求数据类型从未发生过这种情况。

于 2019-10-05T21:39:23.063 回答