使用 django 测试客户端发送 JSON

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8583290/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 18:06:56  来源:igfitidea点击:

Sending JSON using the django test client

djangojsonunit-testing

提问by Hartley Brody

I'm working on a django a project that will serve as the endpoint for a webhook. The webhook will POST some JSON data to my endpoint, which will then parse that data. I'm trying to write unit tests for it, but I'm not sure if I'm sending the JSON properly.

我正在开发一个 django 项目,该项目将作为 webhook 的端点。webhook 会将一些 JSON 数据发布到我的端点,然后该端点将解析该数据。我正在尝试为它编写单元测试,但我不确定我是否正确发送了 JSON。

I keep getting "TypeError: string indices must be integers" in pipeline_endpoint

我在管道端点中不断收到“类型错误:字符串索引必须是整数”

Here's the code:

这是代码:

# 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")

and

# 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'],
        }

Edit: whole 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'...

回答by Guillaume Vincent

@mrmagooey is right

@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")

use json.dumpsinstead of json.loads

使用json.dumps代替json.loads

回答by Chris Lamb

Try:

尝试:

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

回答by amertkara

You can always use the HttpRequest.bodywhich loads the raw request data. This way you can handle your own data processing.

您始终可以使用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)

回答by Du?an Ma?ar

rest_framework's APIClient(which is the the default client_classin APITestCase) takes care of dumping dictto JSONand it sets proper content type by passing format='json'.

rest_frameworkAPIClient(这是默认client_classAPITestCase)开倾倒照顾dictJSON,它通过使设置适当的内容类型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)

回答by czarchaic

You can user iteritemson dictionaries to loop

您可以使用iteritems字典来循环

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

or alternatively

或者

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

回答by Amit Chaudhary

Adding to Guillaume Vincent's answer, from Django 2.1 we no longer need to use json.dumps for passing the data.

除了 Guillaume Vincent 的回答之外,从 Django 2.1 开始,我们不再需要使用 json.dumps 来传递数据。

Changed in Django 2.1: The JSON serialization described above was added. In older versions, you can call json.dumps() on data before passing it to post() to achieve the same thing.

Django 2.1 中的更改:添加了上述 JSON 序列化。在旧版本中,您可以在将数据传递给 post() 之前对数据调用 json.dumps() 以实现相同的目的。