【问题标题】:How to use Django's assertJSONEqual to verify response of view returning JsonResponse如何使用 Django 的 assertJSONEqual 来验证视图返回 JsonResponse 的响应
【发布时间】:2015-02-12 21:03:09
【问题描述】:

我正在使用 Python 3.4 和 Django 1.7。我有一个返回 JsonResponse 的视图。

def add_item_to_collection(request):
    #(...)
    return JsonResponse({'status':'success'})

我想验证该视图是否使用单元测试返回正确的响应:

class AddItemToCollectionTest(TestCase):

    def test_success_when_not_added_before(self):
        response = self.client.post('/add-item-to-collection')
        self.assertEqual(response.status_code, 200)
        self.assertJSONEqual(response.content, {'status': 'success'})

但是assertJSONEqual() 行会引发异常:

Error
Traceback (most recent call last):
  File "E:\Projects\collecthub\app\collecthub\collecting\tests.py", line 148, in test_success_when_added_before
    self.assertJSONEqual(response.content, {'status': 'OK'})
  File "E:\Projects\collecthub\venv\lib\site-packages\django\test\testcases.py", line 675, in assertJSONEqual
    data = json.loads(raw)
  File "C:\Python34\Lib\json\__init__.py", line 312, in loads
    s.__class__.__name__))
TypeError: the JSON object must be str, not 'bytes'

当响应包含 JSON 时,检查响应内容的正确方法是什么?当我尝试将原始值与assertJSONEqual() 中的字典进行比较时,为什么会出现类型错误?

【问题讨论】:

    标签: python django python-3.x django-testing jsonresponse


    【解决方案1】:

    与respondcreate的解决方案类似,您也可以使用Django的force_text(1.5版开始提供),以获得更短的跨平台解决方案:

    from __future__ import unicode_literals
    from django.utils.encoding import force_text
    
    class AddItemToCollectionTest(TestCase):
    
        def test_success_when_not_added_before(self):
            response = self.client.post('/add-item-to-collection')
            self.assertEqual(response.status_code, 200)
    
            self.assertJSONEqual(force_text(response.content), {'status': 'success'})
    

    【讨论】:

      【解决方案2】:

      看起来您正在使用 Python 3,因此您需要将 response.content 转换为 UTF-8 编码字符串,然后再将其传递给 self.assertJSONEqual

      class AddItemToCollectionTest(TestCase):
      
          def test_success_when_not_added_before(self):
              response = self.client.post('/add-item-to-collection')
              self.assertEqual(response.status_code, 200)
              self.assertJSONEqual(
                  str(response.content, encoding='utf8'),
                  {'status': 'success'}
              )
      

      如果您想同时支持 Python 2.7 和 Python 3,请使用 django ships withsix 兼容性库:

      from __future__ import unicode_literals
      from django.utils import six
      
      class AddItemToCollectionTest(TestCase):
      
          def test_success_when_not_added_before(self):
              response = self.client.post('/add-item-to-collection')
              self.assertEqual(response.status_code, 200)
      
              response_content = response.content
              if six.PY3:
                  response_content = str(response_content, encoding='utf8')
      
              self.assertJSONEqual(
                  response_content,
                  {'status': 'success'}
              )
      

      【讨论】:

      • 代替str,这也可以:response.content.decode("utf-8")
      • 感觉使用response.content.decode("utf-8") 更有意义,因为str() 方法不返回字符串
      猜你喜欢
      • 2018-07-27
      • 1970-01-01
      • 2017-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-19
      • 2017-12-24
      • 2017-01-29
      相关资源
      最近更新 更多