2014-12-14 25 views
13

Używam Pythona 3.4 i Django 1.7. Mam widok wracający JsonResponse.Jak używać Django assertJSONEqual do weryfikacji odpowiedzi powracającego widoku JsonResponse

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

Chcę sprawdzić, czy tego poglądu powraca prawidłowa odpowiedź przy użyciu testów jednostkowych:

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

Jednak linia assertJSONEqual() podnosi wyjątek:

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' 

Co jest Thet prawidłowy sposób sprawdzania treść odpowiedzi, kiedy odpowiedź zawiera JSON? Dlaczego pojawia się błąd typu, gdy próbuję porównać nieprzetworzoną wartość z dict w assertJSONEqual()?

Odpowiedz

17

Wygląda na to, że pracujesz z Python 3 tak będziesz musiał obrócić response.content w UTF-8 zakodowany ciąg przed przekazaniem go do 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'} 
     ) 

Jeśli chcesz jednocześnie obsługiwać zarówno Python 2.7 i Python 3, korzystać z biblioteki six kompatybilności że Django ships with:

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

zamiast 'str' to działa zbyt:' response.content.decode ("UTF-8") ' – jaywink

5

Podobnie respondcreate na rozwiązanie, można również użyć Django force_text (dostępny od Vers jonowy 1,5), na krótszym rozwiązanie cross-platformowej:

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