Подтвердить что ты не робот

Как использовать Django assertJSONEqual для проверки ответа на возвращаемый запрос JsonResponse

Я использую Python 3.4 и Django 1.7. У меня есть представление, возвращающее JsonResponse.

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

Я хочу проверить, возвращает ли это представление правильный ответ с помощью unit test:

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? Почему я получаю ошибку типа, когда пытаюсь сравнить значение raw снова с dict в assertJSONEqual()?

4b9b3361

Ответ 1

Похоже, вы работаете с 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, используйте библиотеку совместимости six, которую django отправляет с:

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'}
        )

Ответ 2

Аналогично решению responsecreate, вы также можете использовать 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'})