Separated JSON serialization tests
This commit is contained in:
parent
d3cfdfb508
commit
6dc7af3e01
|
@ -0,0 +1,273 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import json
|
||||
import re
|
||||
|
||||
from django.core import serializers
|
||||
from django.core.serializers.base import DeserializationError
|
||||
from django.test import TestCase, TransactionTestCase
|
||||
|
||||
from .models import Score
|
||||
from .tests import SerializersTestBase, SerializersTransactionTestBase
|
||||
|
||||
|
||||
class JsonSerializerTestCase(SerializersTestBase, TestCase):
|
||||
serializer_name = "json"
|
||||
pkless_str = """[
|
||||
{
|
||||
"pk": null,
|
||||
"model": "serializers.category",
|
||||
"fields": {"name": "Reference"}
|
||||
}, {
|
||||
"model": "serializers.category",
|
||||
"fields": {"name": "Non-fiction"}
|
||||
}]"""
|
||||
mapping_ordering_str = """[
|
||||
{
|
||||
"model": "serializers.article",
|
||||
"pk": %(article_pk)s,
|
||||
"fields": {
|
||||
"author": %(author_pk)s,
|
||||
"headline": "Poker has no place on ESPN",
|
||||
"pub_date": "2006-06-16T11:00:00",
|
||||
"categories": [
|
||||
%(first_category_pk)s,
|
||||
%(second_category_pk)s
|
||||
],
|
||||
"meta_data": []
|
||||
}
|
||||
}
|
||||
]
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _validate_output(serial_str):
|
||||
try:
|
||||
json.loads(serial_str)
|
||||
except Exception:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def _get_pk_values(serial_str):
|
||||
ret_list = []
|
||||
serial_list = json.loads(serial_str)
|
||||
for obj_dict in serial_list:
|
||||
ret_list.append(obj_dict["pk"])
|
||||
return ret_list
|
||||
|
||||
@staticmethod
|
||||
def _get_field_values(serial_str, field_name):
|
||||
ret_list = []
|
||||
serial_list = json.loads(serial_str)
|
||||
for obj_dict in serial_list:
|
||||
if field_name in obj_dict["fields"]:
|
||||
ret_list.append(obj_dict["fields"][field_name])
|
||||
return ret_list
|
||||
|
||||
def test_indentation_whitespace(self):
|
||||
Score.objects.create(score=5.0)
|
||||
Score.objects.create(score=6.0)
|
||||
qset = Score.objects.all()
|
||||
|
||||
s = serializers.json.Serializer()
|
||||
json_data = s.serialize(qset, indent=2)
|
||||
for line in json_data.splitlines():
|
||||
if re.search(r'.+,\s*$', line):
|
||||
self.assertEqual(line, line.rstrip())
|
||||
|
||||
def test_json_deserializer_exception(self):
|
||||
with self.assertRaises(DeserializationError):
|
||||
for obj in serializers.deserialize("json", """[{"pk":1}"""):
|
||||
pass
|
||||
|
||||
def test_helpful_error_message_invalid_pk(self):
|
||||
"""
|
||||
If there is an invalid primary key, the error message should contain
|
||||
the model associated with it.
|
||||
"""
|
||||
test_string = """[{
|
||||
"pk": "badpk",
|
||||
"model": "serializers.player",
|
||||
"fields": {
|
||||
"name": "Bob",
|
||||
"rank": 1,
|
||||
"team": "Team"
|
||||
}
|
||||
}]"""
|
||||
with self.assertRaisesMessage(DeserializationError, "(serializers.player:pk=badpk)"):
|
||||
list(serializers.deserialize('json', test_string))
|
||||
|
||||
def test_helpful_error_message_invalid_field(self):
|
||||
"""
|
||||
If there is an invalid field value, the error message should contain
|
||||
the model associated with it.
|
||||
"""
|
||||
test_string = """[{
|
||||
"pk": "1",
|
||||
"model": "serializers.player",
|
||||
"fields": {
|
||||
"name": "Bob",
|
||||
"rank": "invalidint",
|
||||
"team": "Team"
|
||||
}
|
||||
}]"""
|
||||
expected = "(serializers.player:pk=1) field_value was 'invalidint'"
|
||||
with self.assertRaisesMessage(DeserializationError, expected):
|
||||
list(serializers.deserialize('json', test_string))
|
||||
|
||||
def test_helpful_error_message_for_foreign_keys(self):
|
||||
"""
|
||||
Invalid foreign keys with a natural key should throw a helpful error
|
||||
message, such as what the failing key is.
|
||||
"""
|
||||
test_string = """[{
|
||||
"pk": 1,
|
||||
"model": "serializers.category",
|
||||
"fields": {
|
||||
"name": "Unknown foreign key",
|
||||
"meta_data": [
|
||||
"doesnotexist",
|
||||
"metadata"
|
||||
]
|
||||
}
|
||||
}]"""
|
||||
key = ["doesnotexist", "metadata"]
|
||||
expected = "(serializers.category:pk=1) field_value was '%r'" % key
|
||||
with self.assertRaisesMessage(DeserializationError, expected):
|
||||
list(serializers.deserialize('json', test_string))
|
||||
|
||||
def test_helpful_error_message_for_many2many_non_natural(self):
|
||||
"""
|
||||
Invalid many-to-many keys should throw a helpful error message.
|
||||
"""
|
||||
test_string = """[{
|
||||
"pk": 1,
|
||||
"model": "serializers.article",
|
||||
"fields": {
|
||||
"author": 1,
|
||||
"headline": "Unknown many to many",
|
||||
"pub_date": "2014-09-15T10:35:00",
|
||||
"categories": [1, "doesnotexist"]
|
||||
}
|
||||
}, {
|
||||
"pk": 1,
|
||||
"model": "serializers.author",
|
||||
"fields": {
|
||||
"name": "Agnes"
|
||||
}
|
||||
}, {
|
||||
"pk": 1,
|
||||
"model": "serializers.category",
|
||||
"fields": {
|
||||
"name": "Reference"
|
||||
}
|
||||
}]"""
|
||||
expected = "(serializers.article:pk=1) field_value was 'doesnotexist'"
|
||||
with self.assertRaisesMessage(DeserializationError, expected):
|
||||
list(serializers.deserialize('json', test_string))
|
||||
|
||||
def test_helpful_error_message_for_many2many_natural1(self):
|
||||
"""
|
||||
Invalid many-to-many keys should throw a helpful error message.
|
||||
This tests the code path where one of a list of natural keys is invalid.
|
||||
"""
|
||||
test_string = """[{
|
||||
"pk": 1,
|
||||
"model": "serializers.categorymetadata",
|
||||
"fields": {
|
||||
"kind": "author",
|
||||
"name": "meta1",
|
||||
"value": "Agnes"
|
||||
}
|
||||
}, {
|
||||
"pk": 1,
|
||||
"model": "serializers.article",
|
||||
"fields": {
|
||||
"author": 1,
|
||||
"headline": "Unknown many to many",
|
||||
"pub_date": "2014-09-15T10:35:00",
|
||||
"meta_data": [
|
||||
["author", "meta1"],
|
||||
["doesnotexist", "meta1"],
|
||||
["author", "meta1"]
|
||||
]
|
||||
}
|
||||
}, {
|
||||
"pk": 1,
|
||||
"model": "serializers.author",
|
||||
"fields": {
|
||||
"name": "Agnes"
|
||||
}
|
||||
}]"""
|
||||
key = ["doesnotexist", "meta1"]
|
||||
expected = "(serializers.article:pk=1) field_value was '%r'" % key
|
||||
with self.assertRaisesMessage(DeserializationError, expected):
|
||||
for obj in serializers.deserialize('json', test_string):
|
||||
obj.save()
|
||||
|
||||
def test_helpful_error_message_for_many2many_natural2(self):
|
||||
"""
|
||||
Invalid many-to-many keys should throw a helpful error message. This
|
||||
tests the code path where a natural many-to-many key has only a single
|
||||
value.
|
||||
"""
|
||||
test_string = """[{
|
||||
"pk": 1,
|
||||
"model": "serializers.article",
|
||||
"fields": {
|
||||
"author": 1,
|
||||
"headline": "Unknown many to many",
|
||||
"pub_date": "2014-09-15T10:35:00",
|
||||
"meta_data": [1, "doesnotexist"]
|
||||
}
|
||||
}, {
|
||||
"pk": 1,
|
||||
"model": "serializers.categorymetadata",
|
||||
"fields": {
|
||||
"kind": "author",
|
||||
"name": "meta1",
|
||||
"value": "Agnes"
|
||||
}
|
||||
}, {
|
||||
"pk": 1,
|
||||
"model": "serializers.author",
|
||||
"fields": {
|
||||
"name": "Agnes"
|
||||
}
|
||||
}]"""
|
||||
expected = "(serializers.article:pk=1) field_value was 'doesnotexist'"
|
||||
with self.assertRaisesMessage(DeserializationError, expected):
|
||||
for obj in serializers.deserialize('json', test_string, ignore=False):
|
||||
obj.save()
|
||||
|
||||
|
||||
class JsonSerializerTransactionTestCase(SerializersTransactionTestBase, TransactionTestCase):
|
||||
serializer_name = "json"
|
||||
fwd_ref_str = """[
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "serializers.article",
|
||||
"fields": {
|
||||
"headline": "Forward references pose no problem",
|
||||
"pub_date": "2006-06-16T15:00:00",
|
||||
"categories": [1],
|
||||
"author": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "serializers.category",
|
||||
"fields": {
|
||||
"name": "Reference"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "serializers.author",
|
||||
"fields": {
|
||||
"name": "Agnes"
|
||||
}
|
||||
}]"""
|
|
@ -1,16 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import json
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
from django.core import serializers
|
||||
from django.core.serializers.base import ProgressBar
|
||||
from django.db import connection, transaction
|
||||
from django.test import (
|
||||
SimpleTestCase, TestCase, TransactionTestCase, mock, override_settings,
|
||||
skipUnlessDBFeature,
|
||||
SimpleTestCase, mock, override_settings, skipUnlessDBFeature,
|
||||
)
|
||||
from django.test.utils import Approximate
|
||||
from django.utils.six import StringIO
|
||||
|
@ -320,259 +317,3 @@ class SerializersTransactionTestBase(object):
|
|||
art_obj = Article.objects.all()[0]
|
||||
self.assertEqual(art_obj.categories.all().count(), 1)
|
||||
self.assertEqual(art_obj.author.name, "Agnes")
|
||||
|
||||
|
||||
class JsonSerializerTestCase(SerializersTestBase, TestCase):
|
||||
serializer_name = "json"
|
||||
pkless_str = """[
|
||||
{
|
||||
"pk": null,
|
||||
"model": "serializers.category",
|
||||
"fields": {"name": "Reference"}
|
||||
}, {
|
||||
"model": "serializers.category",
|
||||
"fields": {"name": "Non-fiction"}
|
||||
}]"""
|
||||
mapping_ordering_str = """[
|
||||
{
|
||||
"model": "serializers.article",
|
||||
"pk": %(article_pk)s,
|
||||
"fields": {
|
||||
"author": %(author_pk)s,
|
||||
"headline": "Poker has no place on ESPN",
|
||||
"pub_date": "2006-06-16T11:00:00",
|
||||
"categories": [
|
||||
%(first_category_pk)s,
|
||||
%(second_category_pk)s
|
||||
],
|
||||
"meta_data": []
|
||||
}
|
||||
}
|
||||
]
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _validate_output(serial_str):
|
||||
try:
|
||||
json.loads(serial_str)
|
||||
except Exception:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def _get_pk_values(serial_str):
|
||||
ret_list = []
|
||||
serial_list = json.loads(serial_str)
|
||||
for obj_dict in serial_list:
|
||||
ret_list.append(obj_dict["pk"])
|
||||
return ret_list
|
||||
|
||||
@staticmethod
|
||||
def _get_field_values(serial_str, field_name):
|
||||
ret_list = []
|
||||
serial_list = json.loads(serial_str)
|
||||
for obj_dict in serial_list:
|
||||
if field_name in obj_dict["fields"]:
|
||||
ret_list.append(obj_dict["fields"][field_name])
|
||||
return ret_list
|
||||
|
||||
def test_indentation_whitespace(self):
|
||||
Score.objects.create(score=5.0)
|
||||
Score.objects.create(score=6.0)
|
||||
qset = Score.objects.all()
|
||||
|
||||
s = serializers.json.Serializer()
|
||||
json_data = s.serialize(qset, indent=2)
|
||||
for line in json_data.splitlines():
|
||||
if re.search(r'.+,\s*$', line):
|
||||
self.assertEqual(line, line.rstrip())
|
||||
|
||||
def test_helpful_error_message_invalid_pk(self):
|
||||
"""
|
||||
If there is an invalid primary key, the error message should contain
|
||||
the model associated with it.
|
||||
"""
|
||||
test_string = """[{
|
||||
"pk": "badpk",
|
||||
"model": "serializers.player",
|
||||
"fields": {
|
||||
"name": "Bob",
|
||||
"rank": 1,
|
||||
"team": "Team"
|
||||
}
|
||||
}]"""
|
||||
with self.assertRaisesMessage(serializers.base.DeserializationError, "(serializers.player:pk=badpk)"):
|
||||
list(serializers.deserialize('json', test_string))
|
||||
|
||||
def test_helpful_error_message_invalid_field(self):
|
||||
"""
|
||||
If there is an invalid field value, the error message should contain
|
||||
the model associated with it.
|
||||
"""
|
||||
test_string = """[{
|
||||
"pk": "1",
|
||||
"model": "serializers.player",
|
||||
"fields": {
|
||||
"name": "Bob",
|
||||
"rank": "invalidint",
|
||||
"team": "Team"
|
||||
}
|
||||
}]"""
|
||||
expected = "(serializers.player:pk=1) field_value was 'invalidint'"
|
||||
with self.assertRaisesMessage(serializers.base.DeserializationError, expected):
|
||||
list(serializers.deserialize('json', test_string))
|
||||
|
||||
def test_helpful_error_message_for_foreign_keys(self):
|
||||
"""
|
||||
Invalid foreign keys with a natural key should throw a helpful error
|
||||
message, such as what the failing key is.
|
||||
"""
|
||||
test_string = """[{
|
||||
"pk": 1,
|
||||
"model": "serializers.category",
|
||||
"fields": {
|
||||
"name": "Unknown foreign key",
|
||||
"meta_data": [
|
||||
"doesnotexist",
|
||||
"metadata"
|
||||
]
|
||||
}
|
||||
}]"""
|
||||
key = ["doesnotexist", "metadata"]
|
||||
expected = "(serializers.category:pk=1) field_value was '%r'" % key
|
||||
with self.assertRaisesMessage(serializers.base.DeserializationError, expected):
|
||||
list(serializers.deserialize('json', test_string))
|
||||
|
||||
def test_helpful_error_message_for_many2many_non_natural(self):
|
||||
"""
|
||||
Invalid many-to-many keys should throw a helpful error message.
|
||||
"""
|
||||
test_string = """[{
|
||||
"pk": 1,
|
||||
"model": "serializers.article",
|
||||
"fields": {
|
||||
"author": 1,
|
||||
"headline": "Unknown many to many",
|
||||
"pub_date": "2014-09-15T10:35:00",
|
||||
"categories": [1, "doesnotexist"]
|
||||
}
|
||||
}, {
|
||||
"pk": 1,
|
||||
"model": "serializers.author",
|
||||
"fields": {
|
||||
"name": "Agnes"
|
||||
}
|
||||
}, {
|
||||
"pk": 1,
|
||||
"model": "serializers.category",
|
||||
"fields": {
|
||||
"name": "Reference"
|
||||
}
|
||||
}]"""
|
||||
expected = "(serializers.article:pk=1) field_value was 'doesnotexist'"
|
||||
with self.assertRaisesMessage(serializers.base.DeserializationError, expected):
|
||||
list(serializers.deserialize('json', test_string))
|
||||
|
||||
def test_helpful_error_message_for_many2many_natural1(self):
|
||||
"""
|
||||
Invalid many-to-many keys should throw a helpful error message.
|
||||
This tests the code path where one of a list of natural keys is invalid.
|
||||
"""
|
||||
test_string = """[{
|
||||
"pk": 1,
|
||||
"model": "serializers.categorymetadata",
|
||||
"fields": {
|
||||
"kind": "author",
|
||||
"name": "meta1",
|
||||
"value": "Agnes"
|
||||
}
|
||||
}, {
|
||||
"pk": 1,
|
||||
"model": "serializers.article",
|
||||
"fields": {
|
||||
"author": 1,
|
||||
"headline": "Unknown many to many",
|
||||
"pub_date": "2014-09-15T10:35:00",
|
||||
"meta_data": [
|
||||
["author", "meta1"],
|
||||
["doesnotexist", "meta1"],
|
||||
["author", "meta1"]
|
||||
]
|
||||
}
|
||||
}, {
|
||||
"pk": 1,
|
||||
"model": "serializers.author",
|
||||
"fields": {
|
||||
"name": "Agnes"
|
||||
}
|
||||
}]"""
|
||||
key = ["doesnotexist", "meta1"]
|
||||
expected = "(serializers.article:pk=1) field_value was '%r'" % key
|
||||
with self.assertRaisesMessage(serializers.base.DeserializationError, expected):
|
||||
for obj in serializers.deserialize('json', test_string):
|
||||
obj.save()
|
||||
|
||||
def test_helpful_error_message_for_many2many_natural2(self):
|
||||
"""
|
||||
Invalid many-to-many keys should throw a helpful error message. This
|
||||
tests the code path where a natural many-to-many key has only a single
|
||||
value.
|
||||
"""
|
||||
test_string = """[{
|
||||
"pk": 1,
|
||||
"model": "serializers.article",
|
||||
"fields": {
|
||||
"author": 1,
|
||||
"headline": "Unknown many to many",
|
||||
"pub_date": "2014-09-15T10:35:00",
|
||||
"meta_data": [1, "doesnotexist"]
|
||||
}
|
||||
}, {
|
||||
"pk": 1,
|
||||
"model": "serializers.categorymetadata",
|
||||
"fields": {
|
||||
"kind": "author",
|
||||
"name": "meta1",
|
||||
"value": "Agnes"
|
||||
}
|
||||
}, {
|
||||
"pk": 1,
|
||||
"model": "serializers.author",
|
||||
"fields": {
|
||||
"name": "Agnes"
|
||||
}
|
||||
}]"""
|
||||
expected = "(serializers.article:pk=1) field_value was 'doesnotexist'"
|
||||
with self.assertRaisesMessage(serializers.base.DeserializationError, expected):
|
||||
for obj in serializers.deserialize('json', test_string, ignore=False):
|
||||
obj.save()
|
||||
|
||||
|
||||
class JsonSerializerTransactionTestCase(SerializersTransactionTestBase, TransactionTestCase):
|
||||
serializer_name = "json"
|
||||
fwd_ref_str = """[
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "serializers.article",
|
||||
"fields": {
|
||||
"headline": "Forward references pose no problem",
|
||||
"pub_date": "2006-06-16T15:00:00",
|
||||
"categories": [1],
|
||||
"author": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "serializers.category",
|
||||
"fields": {
|
||||
"name": "Reference"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "serializers.author",
|
||||
"fields": {
|
||||
"name": "Agnes"
|
||||
}
|
||||
}]"""
|
||||
|
|
|
@ -14,7 +14,6 @@ import uuid
|
|||
|
||||
from django.core import serializers
|
||||
from django.core.serializers import SerializerDoesNotExist
|
||||
from django.core.serializers.base import DeserializationError
|
||||
from django.db import connection, models
|
||||
from django.http import HttpResponse
|
||||
from django.test import TestCase, skipUnlessDBFeature
|
||||
|
@ -421,11 +420,6 @@ class SerializerTests(TestCase):
|
|||
with self.assertRaises(SerializerDoesNotExist):
|
||||
serializers.get_deserializer("nonsense")
|
||||
|
||||
def test_json_deserializer_exception(self):
|
||||
with self.assertRaises(DeserializationError):
|
||||
for obj in serializers.deserialize("json", """[{"pk":1}"""):
|
||||
pass
|
||||
|
||||
def test_serialize_proxy_model(self):
|
||||
BaseModel.objects.create(parent_data=1)
|
||||
base_objects = BaseModel.objects.all()
|
||||
|
|
Loading…
Reference in New Issue