当 pytest 与 REST 框架交互时,PATCH 和 PUT 无法按预期工作
PATCH and PUT don't work as expected when pytest is interacting with REST framework
我正在使用 django REST 框架构建 API。
为了测试这个 API 我正在使用 pytest 和测试客户端,如下所示:
def test_doesnt_find(self, client):
resp = client.post(self.url, data={'name': '123'})
assert resp.status_code == 404
或
def test_doesnt_find(self, client):
resp = client.get(self.url, data={'name': '123'})
assert resp.status_code == 404
在使用 REST 框架的一般 GET、POST 和 DELETE 类 时都有效(如 DestroyAPIView
、RetrieveUpdateAPIView
或 APIView
使用get 和 post 函数)
我在使用 PATCH 和 PUT 视图时遇到问题。比如RetrieveUpdateAPIView
。这里突然不得不用:
resp = client.patch(self.url, data="name=123", content_type='application/x-www-form-urlencoded')
或
resp = client.patch(self.url, data=json.dumps({'name': '123'}), content_type='application/json')
如果我只是像往常一样尝试使用测试客户端,我会收到错误消息:
rest_framework.exceptions.UnsupportedMediaType: Unsupported media type "application/octet-stream" in request.
当我在 client.patch() 调用中指定 'application/json' 时:
rest_framework.exceptions.ParseError: JSON parse error - Expecting property name enclosed in double quotes: line 1 column 2 (char 1)`
任何人都可以向我解释这种行为吗?它特别难以捕捉,因为使用 -X PATCH -d"name=123"
.
至于带有 JSON 数据的请求,由于 JSON syntax 您收到此错误,它需要 双引号 字符串。
rest_framework.exceptions.ParseError: JSON parse error - Expecting property name enclosed in double quotes: line 1 column 2 (char 1)`
这通常表示您在 json 中的字符串中发送了一个字符串。
例如:
resp = client.patch(self.url, data=json.dumps("name=123"), content_type='application/json')
会导致此类问题。
rest_framework.exceptions.UnsupportedMediaType: Unsupported media type "application/octet-stream" in request.
这意味着请求已作为 "application/octet-stream" 发送,这是 Django 的测试默认值。
为了减轻处理所有这些的痛苦,Django REST 框架自己提供了一个客户端:http://www.django-rest-framework.org/api-guide/testing/#apiclient
请注意,语法与 Django 的略有不同,您不必处理 json 编码。
Pytest 使用 django 测试客户端 client.post default content_type is multipart/form-data, while put, patch and delete 使用 application/octet-stream.
这就是有时这很棘手的原因。即使是 post 请求,如果您计划支持 JSON 负载,您也必须在测试请求中告知内容类型。无论如何,对于最新的 Django 版本,您只需将数据对象传递给客户端请求,它就会为您序列化,如 docs:
中声明的那样
If you provide content_type as application/json, the data is
serialized using json.dumps() if it’s a dict, list, or tuple.
Serialization is performed with DjangoJSONEncoder by default, and can
be overridden by providing a json_encoder argument to Client. This
serialization also happens for put(), patch(), and delete() requests.
例如:
resp = client.patch(self.url, {'name': '123'}, content_type='application/json')
聚会迟到了。但对于 Google 员工,您应该在 django 测试客户端.
中使用 format='json'
手动 json.dump
和设置 content_type
并不总能按预期工作。
resp = client.patch(self.url, data={'name': '123'}, format='json')
我正在使用 django REST 框架构建 API。
为了测试这个 API 我正在使用 pytest 和测试客户端,如下所示:
def test_doesnt_find(self, client):
resp = client.post(self.url, data={'name': '123'})
assert resp.status_code == 404
或
def test_doesnt_find(self, client):
resp = client.get(self.url, data={'name': '123'})
assert resp.status_code == 404
在使用 REST 框架的一般 GET、POST 和 DELETE 类 时都有效(如 DestroyAPIView
、RetrieveUpdateAPIView
或 APIView
使用get 和 post 函数)
我在使用 PATCH 和 PUT 视图时遇到问题。比如RetrieveUpdateAPIView
。这里突然不得不用:
resp = client.patch(self.url, data="name=123", content_type='application/x-www-form-urlencoded')
或
resp = client.patch(self.url, data=json.dumps({'name': '123'}), content_type='application/json')
如果我只是像往常一样尝试使用测试客户端,我会收到错误消息:
rest_framework.exceptions.UnsupportedMediaType: Unsupported media type "application/octet-stream" in request.
当我在 client.patch() 调用中指定 'application/json' 时:
rest_framework.exceptions.ParseError: JSON parse error - Expecting property name enclosed in double quotes: line 1 column 2 (char 1)`
任何人都可以向我解释这种行为吗?它特别难以捕捉,因为使用 -X PATCH -d"name=123"
.
至于带有 JSON 数据的请求,由于 JSON syntax 您收到此错误,它需要 双引号 字符串。
rest_framework.exceptions.ParseError: JSON parse error - Expecting property name enclosed in double quotes: line 1 column 2 (char 1)`
这通常表示您在 json 中的字符串中发送了一个字符串。 例如:
resp = client.patch(self.url, data=json.dumps("name=123"), content_type='application/json')
会导致此类问题。
rest_framework.exceptions.UnsupportedMediaType: Unsupported media type "application/octet-stream" in request.
这意味着请求已作为 "application/octet-stream" 发送,这是 Django 的测试默认值。
为了减轻处理所有这些的痛苦,Django REST 框架自己提供了一个客户端:http://www.django-rest-framework.org/api-guide/testing/#apiclient
请注意,语法与 Django 的略有不同,您不必处理 json 编码。
Pytest 使用 django 测试客户端 client.post default content_type is multipart/form-data, while put, patch and delete 使用 application/octet-stream.
这就是有时这很棘手的原因。即使是 post 请求,如果您计划支持 JSON 负载,您也必须在测试请求中告知内容类型。无论如何,对于最新的 Django 版本,您只需将数据对象传递给客户端请求,它就会为您序列化,如 docs:
中声明的那样If you provide content_type as application/json, the data is serialized using json.dumps() if it’s a dict, list, or tuple. Serialization is performed with DjangoJSONEncoder by default, and can be overridden by providing a json_encoder argument to Client. This serialization also happens for put(), patch(), and delete() requests.
例如:
resp = client.patch(self.url, {'name': '123'}, content_type='application/json')
聚会迟到了。但对于 Google 员工,您应该在 django 测试客户端.
中使用format='json'
手动 json.dump
和设置 content_type
并不总能按预期工作。
resp = client.patch(self.url, data={'name': '123'}, format='json')