使用django测试客户端发送JSON

2w2cym1i  于 2023-10-21  发布在  Go
关注(0)|答案(7)|浏览(129)

我正在做一个django项目,它将作为webhook的端点。webhook将把一些JSON数据POST到我的端点,然后它将解析这些数据。我正在尝试为它编写单元测试,但我不确定是否正确发送了JSON。
我一直得到“TypeError:pipeline_endpoint中的字符串索引必须是整数
代码如下:

# tests.py
from django.test import TestCase
from django.test.client import Client
import simplejson

class TestPipeline(TestCase):

    def setUp(self):
        """initialize the Django test client"""
        self.c = Client()

    def test_200(self):
        json_string = u'{"1": {"guid": "8a40135230f21bdb0130f21c255c0007", "portalId": 999, "email": "fake@email"}}'
        json_data = simplejson.loads(json_string)
        self.response = self.c.post('/pipeline-endpoint', json_data, content_type="application/json")
        self.assertEqual(self.response.status_code, "200")

# views.py
from pipeline.prospect import Prospect
import simplejson

def pipeline_endpoint(request):

    #get the data from the json object that came in
    prospects_json = simplejson.loads(request.raw_post_data)
    for p in prospects_json:
        prospect = {
            'email'          : p['email'],
            'hs_id'          : p['guid'],
            'portal'         : p['portalId'],
        }

标签:Traceback

======================================================================
ERROR: test_200 (pipeline.tests.TestPipeline)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "F:\......\pipeline\tests.py", line 31, in test_200
    self.response = self.c.post('/pipeline-endpoint', json_string, content_type="application/json")
  File "C:\Python27\lib\site-packages\django\test\client.py", line 455, in post
    response = super(Client, self).post(path, data=data, content_type=content_type, **extra)
  File "C:\Python27\lib\site-packages\django\test\client.py", line 256, in post
    return self.request(**r)
  File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 111, in get_response
    response = callback(request, *callback_args, **callback_kwargs)
  File "F:\......\pipeline\views.py", line 18, in pipeline_endpoint
    'email'          : p['email'],
TypeError: string indices must be integers

----------------------------------------------------------------------
Ran 1 test in 0.095s

FAILED (errors=1)
Destroying test database for alias 'default'...
ndh0cuux

ndh0cuux1#

@mrmagooey是对的

def test_your_test(self):
    python_dict = {
        "1": {
            "guid": "8a40135230f21bdb0130f21c255c0007",
            "portalId": 999,
            "email": "fake@email"
        }
    }
    response = self.client.post('/pipeline-endpoint/',
                                json.dumps(python_dict),
                                content_type="application/json")

使用json.dumps代替json.loads

yyyllmsg

yyyllmsg2#

rest_frameworkAPIClient(这是APITestCase中的默认client_class)负责将dict转储到JSON,并通过传递format='json'来设置适当的内容类型。

from rest_framework import status
from rest_framework.test import APIClient, APITestCase

class MyTestCase(APITestCase):
    url = '/url'

    def post(self, payload, url=None):
        """
        Helper to send an HTTP post.

        @param (dict) payload: request body

        @returns: response
        """
        if url is None:
            url = self.url

        return self.client.post(url, payload, format='json')

    def test_my_function(self):
        payload = {
            'key': 'value'
        }
        response = self.post(payload)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
q9yhzks0

q9yhzks03#

试试看:

self.client.generic('POST', '/url', json.dumps({'json': 'object'})
4si2a6ki

4si2a6ki4#

您可以始终使用HttpRequest.body加载原始请求数据。这样您就可以处理自己的数据处理。

c = Client()
json_str= json.dumps({"data": {"id": 1}})
c.post('/ajax/handler/', data= json_str, content_type='application/json',
                                         HTTP_X_REQUESTED_WITH='XMLHttpRequest')

def index(request):
    ....
    print json.loads(request.body)
aij0ehis

aij0ehis5#

从Django 3.0开始,你可以添加content_type='application/json'并将数据作为Python字典传递。
来自Django文档(提出请求部分):
如果您提供content_type作为application/json,则如果数据是dict、list或tuple,则使用json.dumps()序列化数据。默认情况下,DjangoJSONEncoder会执行序列化,并且可以通过向客户端提供json_encoder参数来覆盖序列化。这种序列化也发生在put()、patch()和delete()请求中。

response = client.post(
    f'/customer/{customer.id}/edit',
    {'email': new_email},
    content_type='application/json'
)
0aydgbwb

0aydgbwb6#

你可以在字典上使用iteritems来循环

for index, p in prospects_json.iteritems():
  prospect={
    'email': p['email'],
  }

或替代地

for index in prospect_json:
  prospect={
    'email': prospect_json[ index ]['email']
  }
oug3syen

oug3syen7#

加上Guillaume Vincent的回答,从Django 2.1开始,我们不再需要使用json.dumps来传递数据。
在Django 2.1中更改:添加了上面描述的JSON序列化。在旧版本中,您可以在将数据传递给post()之前对数据调用json.dumps()来实现相同的功能。

相关问题