Пример #1
0
class TestRuntimeSerialized(unittest.TestCase):
    class TestObj(Model):

        _validation = {}
        _attribute_map = {
            'attr_a': {
                'key': 'id',
                'type': 'str'
            },
            'attr_b': {
                'key': 'AttrB',
                'type': 'int'
            },
            'attr_c': {
                'key': 'Key_C',
                'type': 'bool'
            },
            'attr_d': {
                'key': 'AttrD',
                'type': '[int]'
            },
            'attr_e': {
                'key': 'AttrE',
                'type': '{float}'
            }
        }

        def __init__(self):

            self.attr_a = None
            self.attr_b = None
            self.attr_c = None
            self.attr_d = None
            self.attr_e = None

        def __str__(self):
            return "Test_Object"

    def setUp(self):
        self.s = Serializer()
        return super(TestRuntimeSerialized, self).setUp()

    def test_validate(self):
        # Assert not necessary, should not raise exception
        self.s.validate("simplestring", "StringForLog", pattern="^[a-z]+$")
        self.s.validate(u"UTF8ééééé", "StringForLog", pattern=r"^[\w]+$")

    def test_obj_serialize_none(self):
        """Test that serialize None in object is still None.
        """
        obj = self.s.serialize_object({'test': None})
        self.assertIsNone(obj['test'])

    def test_obj_without_attr_map(self):
        """
        Test serializing an object with no attribute_map.
        """
        test_obj = type("BadTestObj", (), {})

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

    def test_obj_with_malformed_map(self):
        """
        Test serializing an object with a malformed attribute_map.
        """
        test_obj = type("BadTestObj", (Model, ), {"_attribute_map": None})

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

        test_obj._attribute_map = {"attr": "val"}

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

        test_obj._attribute_map = {"attr": {"val": 1}}

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

    def test_obj_with_mismatched_map(self):
        """
        Test serializing an object with mismatching attributes and map.
        """
        test_obj = type("BadTestObj", (Model, ), {"_attribute_map": None})
        test_obj._attribute_map = {"abc": {"key": "ABC", "type": "str"}}

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

    def test_attr_none(self):
        """
        Test serializing an object with None attributes.
        """
        test_obj = self.TestObj()
        message = self.s._serialize(test_obj)

        self.assertIsInstance(message, dict)
        self.assertFalse('id' in message)

    def test_attr_int(self):
        """
        Test serializing an object with Int attributes.
        """
        test_obj = self.TestObj()
        self.TestObj._validation = {
            'attr_b': {
                'required': True
            },
        }
        test_obj.attr_b = None

        with self.assertRaises(ValidationError):
            self.s._serialize(test_obj)

        test_obj.attr_b = 25

        message = self.s._serialize(test_obj)
        self.assertEqual(message['AttrB'], int(test_obj.attr_b))

        test_obj.attr_b = "34534"

        message = self.s._serialize(test_obj)
        self.assertEqual(message['AttrB'], int(test_obj.attr_b))

        test_obj.attr_b = "NotANumber"

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

        self.TestObj._validation = {}

    def test_attr_str(self):
        """
        Test serializing an object with Str attributes.
        """
        test_obj = self.TestObj()
        self.TestObj._validation = {
            'attr_a': {
                'required': True
            },
        }
        test_obj.attr_a = None

        with self.assertRaises(ValidationError):
            self.s._serialize(test_obj)

        self.TestObj._validation = {}
        test_obj.attr_a = "TestString"

        message = self.s._serialize(test_obj)
        self.assertEqual(message['id'], str(test_obj.attr_a))

        test_obj.attr_a = 1234

        message = self.s._serialize(test_obj)
        self.assertEqual(message['id'], str(test_obj.attr_a))

        test_obj.attr_a = list()

        message = self.s._serialize(test_obj)
        self.assertEqual(message['id'], str(test_obj.attr_a))

        test_obj.attr_a = [1]

        message = self.s._serialize(test_obj)
        self.assertEqual(message['id'], str(test_obj.attr_a))

    def test_attr_bool(self):
        """
        Test serializing an object with bool attributes.
        """
        test_obj = self.TestObj()
        test_obj.attr_c = True

        message = self.s._serialize(test_obj)
        self.assertEqual(message['Key_C'], True)

        test_obj.attr_c = ""

        message = self.s._serialize(test_obj)
        self.assertTrue('Key_C' in message)

        test_obj.attr_c = None

        message = self.s._serialize(test_obj)
        self.assertFalse('Key_C' in message)

        test_obj.attr_c = "NotEmpty"

        message = self.s._serialize(test_obj)
        self.assertEqual(message['Key_C'], True)

    def test_attr_sequence(self):
        """
        Test serializing a sequence.
        """

        test_obj = ["A", "B", "C"]
        output = self.s._serialize(test_obj, '[str]', div='|')
        self.assertEqual(output, "|".join(test_obj))

        test_obj = [1, 2, 3]
        output = self.s._serialize(test_obj, '[str]', div=',')
        self.assertEqual(output, ",".join([str(i) for i in test_obj]))

    def test_attr_list_simple(self):
        """
        Test serializing an object with simple-typed list attributes
        """
        test_obj = self.TestObj()
        test_obj.attr_d = []

        message = self.s._serialize(test_obj)
        self.assertEqual(message['AttrD'], test_obj.attr_d)

        test_obj.attr_d = [1, 2, 3]

        message = self.s._serialize(test_obj)
        self.assertEqual(message['AttrD'], test_obj.attr_d)

        test_obj.attr_d = ["1", "2", "3"]

        message = self.s._serialize(test_obj)
        self.assertEqual(message['AttrD'], [int(i) for i in test_obj.attr_d])

        test_obj.attr_d = ["test", "test2", "test3"]

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

        test_obj.attr_d = "NotAList"

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

    def test_empty_list(self):

        input = []
        output = self.s._serialize(input, '[str]')
        self.assertEqual(output, input)

    def test_attr_list_complex(self):
        """
        Test serializing an object with a list of complex objects as an attribute.
        """
        list_obj = type("ListObj", (Model, ), {
            "_attribute_map": None,
            "_validation": {},
            "abc": None
        })
        list_obj._attribute_map = {"abc": {"key": "ABC", "type": "int"}}
        list_obj.abc = "123"

        test_obj = type("CmplxTestObj", (Model, ), {
            "_attribute_map": None,
            "_validation": {},
            "test_list": None
        })

        test_obj._attribute_map = {
            "test_list": {
                "key": "_list",
                "type": "[ListObj]"
            }
        }
        test_obj.test_list = [list_obj]

        message = self.s._serialize(test_obj)
        self.assertEqual(message, {'_list': [{'ABC': 123}]})

        list_obj = type("BadListObj", (Model, ), {"map": None})
        test_obj._attribute_map = {
            "test_list": {
                "key": "_list",
                "type": "[BadListObj]"
            }
        }
        test_obj.test_list = [list_obj]

        s = self.s._serialize(test_obj)
        self.assertEqual(s, {'_list': [{}]})

    def test_attr_dict_simple(self):
        """
        Test serializing an object with a simple dictionary attribute.
        """

        test_obj = self.TestObj()
        test_obj.attr_e = {"value": 3.14}

        message = self.s._serialize(test_obj)
        self.assertEqual(message['AttrE']['value'],
                         float(test_obj.attr_e["value"]))

        test_obj.attr_e = {1: "3.14"}

        message = self.s._serialize(test_obj)
        self.assertEqual(message['AttrE']['1'], float(test_obj.attr_e[1]))

        test_obj.attr_e = "NotADict"

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

        test_obj.attr_e = {"value": "NotAFloat"}

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

    def test_serialize_datetime(self):

        date_obj = isodate.parse_datetime('2015-01-01T00:00:00')
        date_str = Serializer.serialize_iso(date_obj)

        self.assertEqual(date_str, '2015-01-01T00:00:00.000Z')

        date_obj = isodate.parse_datetime('1999-12-31T23:59:59-12:00')
        date_str = Serializer.serialize_iso(date_obj)

        self.assertEqual(date_str, '2000-01-01T11:59:59.000Z')

        with self.assertRaises(SerializationError):
            date_obj = isodate.parse_datetime('9999-12-31T23:59:59-12:00')
            date_str = Serializer.serialize_iso(date_obj)

        with self.assertRaises(SerializationError):
            date_obj = isodate.parse_datetime('0001-01-01T00:00:00+23:59')
            date_str = Serializer.serialize_iso(date_obj)

        date_obj = isodate.parse_datetime("2015-06-01T16:10:08.0121-07:00")
        date_str = Serializer.serialize_iso(date_obj)

        self.assertEqual(date_str, '2015-06-01T23:10:08.0121Z')

        date_obj = datetime.min
        date_str = Serializer.serialize_iso(date_obj)
        self.assertEqual(date_str, '0001-01-01T00:00:00.000Z')

        date_obj = datetime.max
        date_str = Serializer.serialize_iso(date_obj)
        self.assertEqual(date_str, '9999-12-31T23:59:59.999999Z')

    def test_serialize_primitive_types(self):

        a = self.s.serialize_data(1, 'int')
        self.assertEqual(a, 1)

        b = self.s.serialize_data(True, 'bool')
        self.assertEqual(b, True)

        c = self.s.serialize_data('True', 'str')
        self.assertEqual(c, 'True')

        d = self.s.serialize_data(100.0123, 'float')
        self.assertEqual(d, 100.0123)

    def test_serialize_object(self):

        a = self.s.body(1, 'object')
        self.assertEqual(a, 1)

        b = self.s.body(True, 'object')
        self.assertEqual(b, True)

        c = self.s.serialize_data('True', 'object')
        self.assertEqual(c, 'True')

        d = self.s.serialize_data(100.0123, 'object')
        self.assertEqual(d, 100.0123)

        e = self.s.serialize_data({}, 'object')
        self.assertEqual(e, {})

        f = self.s.body({"test": "data"}, 'object')
        self.assertEqual(f, {"test": "data"})

        g = self.s.body({"test": {"value": "data"}}, 'object')
        self.assertEqual(g, {"test": {"value": "data"}})

        h = self.s.serialize_data({"test": self.TestObj()}, 'object')
        self.assertEqual(h, {"test": "Test_Object"})

        i = self.s.serialize_data({"test": [1, 2, 3, 4, 5]}, 'object')
        self.assertEqual(i, {"test": [1, 2, 3, 4, 5]})

    def test_serialize_empty_iter(self):

        a = self.s.serialize_dict({}, 'int')
        self.assertEqual(a, {})

        b = self.s.serialize_iter([], 'int')
        self.assertEqual(b, [])

    def test_serialize_json_obj(self):
        class ComplexId(Model):

            _validation = {}
            _attribute_map = {
                'id': {
                    'key': 'id',
                    'type': 'int'
                },
                'name': {
                    'key': 'name',
                    'type': 'str'
                },
                'age': {
                    'key': 'age',
                    'type': 'float'
                },
                'male': {
                    'key': 'male',
                    'type': 'bool'
                },
                'birthday': {
                    'key': 'birthday',
                    'type': 'iso-8601'
                },
                'anniversary': {
                    'key': 'anniversary',
                    'type': 'iso-8601'
                }
            }

            id = 1
            name = "Joey"
            age = 23.36
            male = True
            birthday = '1992-01-01T00:00:00.000Z'
            anniversary = isodate.parse_datetime('2013-12-08T00:00:00')

        class ComplexJson(Model):

            _validation = {}
            _attribute_map = {
                'p1': {
                    'key': 'p1',
                    'type': 'str'
                },
                'p2': {
                    'key': 'p2',
                    'type': 'str'
                },
                'top_date': {
                    'key': 'top_date',
                    'type': 'iso-8601'
                },
                'top_dates': {
                    'key': 'top_dates',
                    'type': '[iso-8601]'
                },
                'insider': {
                    'key': 'insider',
                    'type': '{iso-8601}'
                },
                'top_complex': {
                    'key': 'top_complex',
                    'type': 'ComplexId'
                }
            }

            p1 = 'value1'
            p2 = 'value2'
            top_date = isodate.parse_datetime('2014-01-01T00:00:00')
            top_dates = [
                isodate.parse_datetime('1900-01-01T00:00:00'),
                isodate.parse_datetime('1901-01-01T00:00:00')
            ]
            insider = {
                'k1': isodate.parse_datetime('2015-01-01T00:00:00'),
                'k2': isodate.parse_datetime('2016-01-01T00:00:00'),
                'k3': isodate.parse_datetime('2017-01-01T00:00:00')
            }
            top_complex = ComplexId()

        message = self.s._serialize(ComplexJson())

        output = {
            'p1': 'value1',
            'p2': 'value2',
            'top_date': '2014-01-01T00:00:00.000Z',
            'top_dates':
            ['1900-01-01T00:00:00.000Z', '1901-01-01T00:00:00.000Z'],
            'insider': {
                'k1': '2015-01-01T00:00:00.000Z',
                'k2': '2016-01-01T00:00:00.000Z',
                'k3': '2017-01-01T00:00:00.000Z'
            },
            'top_complex': {
                'id': 1,
                'name': 'Joey',
                'age': 23.36,
                'male': True,
                'birthday': '1992-01-01T00:00:00.000Z',
                'anniversary': '2013-12-08T00:00:00.000Z',
            }
        }
        self.maxDiff = None
        self.assertEqual(message, output)

    def test_polymorphic_serialization(self):

        self.maxDiff = None

        class Zoo(Model):

            _attribute_map = {
                "animals": {
                    "key": "Animals",
                    "type": "[Animal]"
                },
            }

            def __init__(self, animals=None):
                self.animals = animals

        class Animal(Model):

            _attribute_map = {
                "name": {
                    "key": "Name",
                    "type": "str"
                },
                "d_type": {
                    "key": "dType",
                    "type": "str"
                }
            }

            _subtype_map = {'d_type': {"cat": "Cat", "dog": "Dog"}}

            def __init__(self, name=None):
                self.name = name

        class Dog(Animal):

            _attribute_map = {
                "name": {
                    "key": "Name",
                    "type": "str"
                },
                "likes_dog_food": {
                    "key": "likesDogFood",
                    "type": "bool"
                },
                "d_type": {
                    "key": "dType",
                    "type": "str"
                }
            }

            def __init__(self, name=None, likes_dog_food=None):
                self.likes_dog_food = likes_dog_food
                super(Dog, self).__init__(name)
                self.d_type = 'dog'

        class Cat(Animal):

            _attribute_map = {
                "name": {
                    "key": "Name",
                    "type": "str"
                },
                "likes_mice": {
                    "key": "likesMice",
                    "type": "bool"
                },
                "dislikes": {
                    "key": "dislikes",
                    "type": "Animal"
                },
                "d_type": {
                    "key": "dType",
                    "type": "str"
                }
            }

            _subtype_map = {"d_type": {"siamese": "Siamese"}}

            def __init__(self, name=None, likes_mice=None, dislikes=None):
                self.likes_mice = likes_mice
                self.dislikes = dislikes
                super(Cat, self).__init__(name)
                self.d_type = 'cat'

        class Siamese(Cat):

            _attribute_map = {
                "name": {
                    "key": "Name",
                    "type": "str"
                },
                "likes_mice": {
                    "key": "likesMice",
                    "type": "bool"
                },
                "dislikes": {
                    "key": "dislikes",
                    "type": "Animal"
                },
                "color": {
                    "key": "Color",
                    "type": "str"
                },
                "d_type": {
                    "key": "dType",
                    "type": "str"
                }
            }

            def __init__(self,
                         name=None,
                         likes_mice=None,
                         dislikes=None,
                         color=None):
                self.color = color
                super(Siamese, self).__init__(name, likes_mice, dislikes)
                self.d_type = 'siamese'

        message = {
            "Animals": [{
                "dType": "dog",
                "likesDogFood": True,
                "Name": "Fido"
            }, {
                "dType": "cat",
                "likesMice": False,
                "dislikes": {
                    "dType": "dog",
                    "likesDogFood": True,
                    "Name": "Angry"
                },
                "Name": "Felix"
            }, {
                "dType": "siamese",
                "Color": "grey",
                "likesMice": True,
                "Name": "Finch"
            }]
        }

        zoo = Zoo()
        angry = Dog()
        angry.name = "Angry"
        angry.likes_dog_food = True

        fido = Dog()
        fido.name = "Fido"
        fido.likes_dog_food = True

        felix = Cat()
        felix.name = "Felix"
        felix.likes_mice = False
        felix.dislikes = angry

        finch = Siamese()
        finch.name = "Finch"
        finch.color = "grey"
        finch.likes_mice = True

        zoo.animals = [fido, felix, finch]

        serialized = self.s._serialize(zoo)
        self.assertEqual(serialized, message)

        old_dependencies = self.s.dependencies
        self.s.dependencies = {
            'Zoo': Zoo,
            'Animal': Animal,
            'Dog': Dog,
            'Cat': Cat,
            'Siamese': Siamese
        }

        serialized = self.s.body(
            {
                "animals": [{
                    "dType": "dog",
                    "likes_dog_food": True,
                    "name": "Fido"
                }, {
                    "dType": "cat",
                    "likes_mice": False,
                    "dislikes": {
                        "dType": "dog",
                        "likes_dog_food": True,
                        "name": "Angry"
                    },
                    "name": "Felix"
                }, {
                    "dType": "siamese",
                    "color": "grey",
                    "likes_mice": True,
                    "name": "Finch"
                }]
            }, "Zoo")
        self.assertEqual(serialized, message)

        self.s.dependencies = old_dependencies
Пример #2
0
class TestRuntimeSerialized(unittest.TestCase):

    class TestObj(Model):

        _validation = {}
        _attribute_map = {
            'attr_a': {'key':'id', 'type':'str'},
            'attr_b': {'key':'AttrB', 'type':'int'},
            'attr_c': {'key':'Key_C', 'type': 'bool'},
            'attr_d': {'key':'AttrD', 'type':'[int]'},
            'attr_e': {'key':'AttrE', 'type': '{float}'}
            }

        def __init__(self):

            self.attr_a = None
            self.attr_b = None
            self.attr_c = None
            self.attr_d = None
            self.attr_e = None

        def __str__(self):
            return "Test_Object"

    def setUp(self):
        self.s = Serializer()
        return super(TestRuntimeSerialized, self).setUp()

    def test_obj_serialize_none(self):
        """Test that serialize None in object is still None.
        """
        obj = self.s.serialize_object({'test': None})
        self.assertIsNone(obj['test'])

    def test_obj_without_attr_map(self):
        """
        Test serializing an object with no attribute_map.
        """
        test_obj = type("BadTestObj", (), {})

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

    def test_obj_with_malformed_map(self):
        """
        Test serializing an object with a malformed attribute_map.
        """
        test_obj = type("BadTestObj", (Model,), {"_attribute_map":None})

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

        test_obj._attribute_map = {"attr":"val"}

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

        test_obj._attribute_map = {"attr":{"val":1}}

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

    def test_obj_with_mismatched_map(self):
        """
        Test serializing an object with mismatching attributes and map.
        """
        test_obj = type("BadTestObj", (Model,), {"_attribute_map":None})
        test_obj._attribute_map = {"abc":{"key":"ABC", "type":"str"}}

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

    def test_attr_none(self):
        """
        Test serializing an object with None attributes.
        """
        test_obj = self.TestObj()
        message = self.s._serialize(test_obj)

        self.assertIsInstance(message, dict)
        self.assertFalse('id' in message)

    def test_attr_int(self):
        """
        Test serializing an object with Int attributes.
        """
        test_obj = self.TestObj()
        self.TestObj._validation = {
            'attr_b': {'required': True},
        }
        test_obj.attr_b = None

        with self.assertRaises(ValidationError):
            self.s._serialize(test_obj)

        test_obj.attr_b = 25

        message = self.s._serialize(test_obj)
        self.assertEqual(message['AttrB'], int(test_obj.attr_b))

        test_obj.attr_b = "34534"

        message = self.s._serialize(test_obj)
        self.assertEqual(message['AttrB'], int(test_obj.attr_b))

        test_obj.attr_b = "NotANumber"

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

        self.TestObj._validation = {}

    def test_attr_str(self):
        """
        Test serializing an object with Str attributes.
        """
        test_obj = self.TestObj()
        self.TestObj._validation = {
            'attr_a': {'required': True},
        }
        test_obj.attr_a = None

        with self.assertRaises(ValidationError):
            self.s._serialize(test_obj)

        self.TestObj._validation = {}
        test_obj.attr_a = "TestString"

        message = self.s._serialize(test_obj)
        self.assertEqual(message['id'], str(test_obj.attr_a))

        test_obj.attr_a = 1234

        message = self.s._serialize(test_obj)
        self.assertEqual(message['id'], str(test_obj.attr_a))

        test_obj.attr_a = list()

        message = self.s._serialize(test_obj)
        self.assertEqual(message['id'], str(test_obj.attr_a))

        test_obj.attr_a = [1]

        message = self.s._serialize(test_obj)
        self.assertEqual(message['id'], str(test_obj.attr_a))

    def test_attr_bool(self):
        """
        Test serializing an object with bool attributes.
        """
        test_obj = self.TestObj()
        test_obj.attr_c = True

        message = self.s._serialize(test_obj)
        self.assertEqual(message['Key_C'], True)

        test_obj.attr_c = ""

        message = self.s._serialize(test_obj)
        self.assertTrue('Key_C' in message)

        test_obj.attr_c = None

        message = self.s._serialize(test_obj)
        self.assertFalse('Key_C' in message)

        test_obj.attr_c = "NotEmpty"

        message = self.s._serialize(test_obj)
        self.assertEqual(message['Key_C'], True)

    def test_attr_sequence(self):
        """
        Test serializing a sequence.
        """

        test_obj = ["A", "B", "C"]
        output = self.s._serialize(test_obj, '[str]', div='|')
        self.assertEqual(output, "|".join(test_obj))

        test_obj = [1,2,3]
        output = self.s._serialize(test_obj, '[str]', div=',')
        self.assertEqual(output, ",".join([str(i) for i in test_obj]))

    def test_attr_list_simple(self):
        """
        Test serializing an object with simple-typed list attributes
        """
        test_obj = self.TestObj()
        test_obj.attr_d = []

        message = self.s._serialize(test_obj)
        self.assertEqual(message['AttrD'], test_obj.attr_d)

        test_obj.attr_d = [1,2,3]

        message = self.s._serialize(test_obj)
        self.assertEqual(message['AttrD'], test_obj.attr_d)

        test_obj.attr_d = ["1","2","3"]

        message = self.s._serialize(test_obj)
        self.assertEqual(message['AttrD'], [int(i) for i in test_obj.attr_d])

        test_obj.attr_d = ["test","test2","test3"]

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

        test_obj.attr_d = "NotAList"

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

    def test_empty_list(self):

        input = []
        output = self.s._serialize(input, '[str]')
        self.assertEqual(output, input)

    def test_attr_list_complex(self):
        """
        Test serializing an object with a list of complex objects as an attribute.
        """
        list_obj = type("ListObj", (Model,), {"_attribute_map":None,
                                        "_validation":{},
                                        "abc":None})
        list_obj._attribute_map = {"abc":{"key":"ABC", "type":"int"}}
        list_obj.abc = "123"

        test_obj = type("CmplxTestObj", (Model,), {"_attribute_map":None,
                                             "_validation":{},
                                             "test_list":None})

        test_obj._attribute_map = {"test_list":{"key":"_list", "type":"[ListObj]"}}
        test_obj.test_list = [list_obj]

        message = self.s._serialize(test_obj)
        self.assertEqual(message, {'_list':[{'ABC':123}]})

        list_obj = type("BadListObj", (Model,), {"map":None})
        test_obj._attribute_map = {"test_list":{"key":"_list", "type":"[BadListObj]"}}
        test_obj.test_list = [list_obj]

        s = self.s._serialize(test_obj)
        self.assertEqual(s, {'_list':[{}]})

    def test_attr_dict_simple(self):
        """
        Test serializing an object with a simple dictionary attribute.
        """

        test_obj = self.TestObj()
        test_obj.attr_e = {"value": 3.14}

        message = self.s._serialize(test_obj)
        self.assertEqual(message['AttrE']['value'], float(test_obj.attr_e["value"]))

        test_obj.attr_e = {1: "3.14"}

        message = self.s._serialize(test_obj)
        self.assertEqual(message['AttrE']['1'], float(test_obj.attr_e[1]))

        test_obj.attr_e = "NotADict"

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

        test_obj.attr_e = {"value": "NotAFloat"}

        with self.assertRaises(SerializationError):
            self.s._serialize(test_obj)

    def test_serialize_datetime(self):

        date_obj = isodate.parse_datetime('2015-01-01T00:00:00')
        date_str = Serializer.serialize_iso(date_obj)

        self.assertEqual(date_str, '2015-01-01T00:00:00.000Z')

        date_obj = isodate.parse_datetime('1999-12-31T23:59:59-12:00')
        date_str = Serializer.serialize_iso(date_obj)

        self.assertEqual(date_str, '2000-01-01T11:59:59.000Z')

        with self.assertRaises(SerializationError):
            date_obj = isodate.parse_datetime('9999-12-31T23:59:59-12:00')
            date_str = Serializer.serialize_iso(date_obj)

        with self.assertRaises(SerializationError):
            date_obj = isodate.parse_datetime('0001-01-01T00:00:00+23:59')
            date_str = Serializer.serialize_iso(date_obj)


        date_obj = isodate.parse_datetime("2015-06-01T16:10:08.0121-07:00")
        date_str = Serializer.serialize_iso(date_obj)

        self.assertEqual(date_str, '2015-06-01T23:10:08.0121Z')

        date_obj = datetime.min
        date_str = Serializer.serialize_iso(date_obj)
        self.assertEqual(date_str, '0001-01-01T00:00:00.000Z')

        date_obj = datetime.max
        date_str = Serializer.serialize_iso(date_obj)
        self.assertEqual(date_str, '9999-12-31T23:59:59.999999Z')


    def test_serialize_primitive_types(self):

        a = self.s.serialize_data(1, 'int')
        self.assertEqual(a, 1)

        b = self.s.serialize_data(True, 'bool')
        self.assertEqual(b, True)

        c = self.s.serialize_data('True', 'str')
        self.assertEqual(c, 'True')

        d = self.s.serialize_data(100.0123, 'float')
        self.assertEqual(d, 100.0123)

    def test_serialize_object(self):

        a = self.s.body(1, 'object')
        self.assertEqual(a, 1)

        b = self.s.body(True, 'object')
        self.assertEqual(b, True)

        c = self.s.serialize_data('True', 'object')
        self.assertEqual(c, 'True')

        d = self.s.serialize_data(100.0123, 'object')
        self.assertEqual(d, 100.0123)

        e = self.s.serialize_data({}, 'object')
        self.assertEqual(e, {})

        f = self.s.body({"test":"data"}, 'object')
        self.assertEqual(f, {"test":"data"})

        g = self.s.body({"test":{"value":"data"}}, 'object')
        self.assertEqual(g, {"test":{"value":"data"}})

        h = self.s.serialize_data({"test":self.TestObj()}, 'object')
        self.assertEqual(h, {"test":"Test_Object"})

        i =  self.s.serialize_data({"test":[1,2,3,4,5]}, 'object')
        self.assertEqual(i, {"test":[1,2,3,4,5]})

    def test_serialize_empty_iter(self):

        a = self.s.serialize_dict({}, 'int')
        self.assertEqual(a, {})

        b = self.s.serialize_iter([], 'int')
        self.assertEqual(b, [])

    def test_serialize_json_obj(self):

        class ComplexId(Model):

            _validation = {}
            _attribute_map = {'id':{'key':'id','type':'int'},
                              'name':{'key':'name','type':'str'},
                              'age':{'key':'age','type':'float'},
                              'male':{'key':'male','type':'bool'},
                              'birthday':{'key':'birthday','type':'iso-8601'},
                              'anniversary':{'key':'anniversary', 'type':'iso-8601'}}

            id = 1
            name = "Joey"
            age = 23.36
            male = True
            birthday = '1992-01-01T00:00:00.000Z'
            anniversary = isodate.parse_datetime('2013-12-08T00:00:00')

        class ComplexJson(Model):

            _validation = {}
            _attribute_map = {'p1':{'key':'p1','type':'str'},
                              'p2':{'key':'p2','type':'str'},
                              'top_date':{'key':'top_date', 'type':'iso-8601'},
                              'top_dates':{'key':'top_dates', 'type':'[iso-8601]'},
                              'insider':{'key':'insider','type':'{iso-8601}'},
                              'top_complex':{'key':'top_complex','type':'ComplexId'}}

            p1 = 'value1'
            p2 = 'value2'
            top_date = isodate.parse_datetime('2014-01-01T00:00:00')
            top_dates = [isodate.parse_datetime('1900-01-01T00:00:00'), isodate.parse_datetime('1901-01-01T00:00:00')]
            insider = {
                'k1': isodate.parse_datetime('2015-01-01T00:00:00'),
                'k2': isodate.parse_datetime('2016-01-01T00:00:00'),
                'k3': isodate.parse_datetime('2017-01-01T00:00:00')}
            top_complex = ComplexId()

        message =self.s._serialize(ComplexJson())

        output = { 
            'p1': 'value1', 
            'p2': 'value2', 
            'top_date': '2014-01-01T00:00:00.000Z', 
            'top_dates': [ 
                '1900-01-01T00:00:00.000Z', 
                '1901-01-01T00:00:00.000Z' 
            ], 
            'insider': {
                'k1': '2015-01-01T00:00:00.000Z', 
                'k2': '2016-01-01T00:00:00.000Z', 
                'k3': '2017-01-01T00:00:00.000Z' 
            }, 
            'top_complex': { 
                'id': 1, 
                'name': 'Joey', 
                'age': 23.36, 
                'male': True, 
                'birthday': '1992-01-01T00:00:00.000Z', 
                'anniversary': '2013-12-08T00:00:00.000Z', 
            } 
        }
        self.maxDiff = None
        self.assertEqual(message, output) 

    def test_polymorphic_serialization(self):

        self.maxDiff = None
        class Zoo(Model):

            _attribute_map = {
                "animals":{"key":"Animals", "type":"[Animal]"},
                }

            def __init__(self):
                self.animals = None

        class Animal(Model):

            _attribute_map = {
                "name":{"key":"Name", "type":"str"}
                }

            _subtype_map = {
                'dType': {"cat":"Cat", "dog":"Dog"}
                }

            def __init__(self):
                self.name = None

        class Dog(Animal):

            _attribute_map = {
                "name":{"key":"Name", "type":"str"},
                "likes_dog_food":{"key":"likesDogFood","type":"bool"}
                }

            def __init__(self):
                self.likes_dog_food = None
                super(Dog, self).__init__()

        class Cat(Animal):

            _attribute_map = {
                "name":{"key":"Name", "type":"str"},
                "likes_mice":{"key":"likesMice","type":"bool"},
                "dislikes":{"key":"dislikes","type":"Animal"}
                }

            _subtype_map = {
                "dType":{"siamese":"Siamese"}
                }

            def __init__(self):
                self.likes_mice = None
                self.dislikes = None
                super(Cat, self).__init__()

        class Siamese(Cat):

            _attribute_map = {
                "name":{"key":"Name", "type":"str"},
                "likes_mice":{"key":"likesMice","type":"bool"},
                "dislikes":{"key":"dislikes","type":"Animal"},
                "color":{"key":"Color", "type":"str"}
                }

            def __init__(self):
                self.color = None
                super(Siamese, self).__init__()

        message = {
            "Animals": [ 
            { 
            "dType": "dog", 
            "likesDogFood": True, 
            "Name": "Fido" 
            }, 
            { 
            "dType": "cat", 
            "likesMice": False, 
            "dislikes": { 
            "dType": "dog", 
            "likesDogFood": True, 
            "Name": "Angry" 
            }, 
            "Name": "Felix" 
            }, 
            { 
            "dType": "siamese", 
            "Color": "grey", 
            "likesMice": True, 
            "Name": "Finch" 
            }]}

        zoo = Zoo()
        angry = Dog()
        angry.name = "Angry"
        angry.likes_dog_food = True

        fido = Dog()
        fido.name = "Fido"
        fido.likes_dog_food = True

        felix = Cat()
        felix.name = "Felix"
        felix.likes_mice = False
        felix.dislikes = angry

        finch = Siamese()
        finch.name = "Finch"
        finch.color = "grey"
        finch.likes_mice = True

        zoo.animals = [fido, felix, finch]

        serialized = self.s._serialize(zoo)
        self.assertEqual(serialized, message)