web-dev-qa-db-ja.com

DjangoのassertJSONEqualを使用して、JsonResponseを返すビューの応答を確認する方法

私は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()のdictと再度比較しようとすると、型エラーが発生するのはなぜですか?

21
Mariusz Jamro

Python 3を使用しているようです。response.contentに渡す前に、self.assertJSONEqualをUTF-8エンコードされた文字列に変換する必要があります。

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 同梱 であるsix互換性ライブラリを使用します。

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

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