예제 #1
0
        public void ReadInline_ThrowsArgumentNull_Item()
        {
            // Arrange
            var deserializer = new ODataResourceDeserializer(_deserializerProvider);

            // Act & Assert
            Assert.ThrowsArgumentNull(
                () => deserializer.ReadInline(item: null, edmType: _productEdmType, readContext: new ODataDeserializerContext()),
                "item");
        }
예제 #2
0
        public void Read_ThrowsOnUnknownEntityType()
        {
            // Arrange
            string content = Resources.SupplierRequestEntry;
            ODataResourceDeserializer deserializer = new ODataResourceDeserializer(_deserializerProvider);

            // Act & Assert
            Assert.Throws <ODataException>(() => deserializer.Read(GetODataMessageReader(GetODataMessage(content), _edmModel),
                                                                   typeof(Product), _readContext), "The property 'Concurrency' does not exist on type 'ODataDemo.Product'. Make sure to only use property names that are defined by the type or mark the type as open type.");
        }
        public void ReadResource_ThrowsArgumentNull_ReadContext()
        {
            // Arrange
            var deserializer = new ODataResourceDeserializer(_deserializerProvider);
            ODataResourceWrapper resourceWrapper = new ODataResourceWrapper(new ODataResource());

            // Act & Assert
            Assert.ThrowsArgumentNull(
                () => deserializer.ReadResource(resourceWrapper, structuredType: _productEdmType, readContext: null),
                "readContext");
        }
        public void ReadInline_Throws_ArgumentMustBeOfType()
        {
            // Arrange
            var deserializer = new ODataResourceDeserializer(_deserializerProvider);

            // Act & Assert
            Assert.ThrowsArgument(
                () => deserializer.ReadInline(item: 42, edmType: _productEdmType, readContext: new ODataDeserializerContext()),
                "item",
                "The argument must be of type 'ODataResource'");
        }
        public void ApplyNestedProperty_ThrowsArgumentNull_ResourceInfoWrapper()
        {
            // Arrange
            var deserializer = new ODataResourceDeserializer(_deserializerProvider);

            // Act & Assert
            Assert.ThrowsArgumentNull(
                () => deserializer.ApplyNestedProperty(42, resourceInfoWrapper: null, structuredType: _productEdmType,
                                                       readContext: _readContext),
                "resourceInfoWrapper");
        }
        public void CreateResourceInstance_ThrowsArgument_ModelMissingFromReadContext()
        {
            // Arrange
            var deserializer = new ODataResourceDeserializer(_deserializerProvider);

            // Act & Assert
            Assert.ThrowsArgument(
                () => deserializer.CreateResourceInstance(_productEdmType, new ODataDeserializerContext()),
                "readContext",
                "The EDM model is missing on the read context. The model is required on the read context to deserialize the payload.");
        }
        public void CreateResourceInstance_ThrowsODataException_MappingDoesNotContainEntityType()
        {
            // Arrange
            var deserializer = new ODataResourceDeserializer(_deserializerProvider);

            // Act & Assert
            Assert.Throws <ODataException>(
                () => deserializer.CreateResourceInstance(_productEdmType, new ODataDeserializerContext {
                Model = EdmCoreModel.Instance
            }),
                "The provided mapping does not contain a resource for the resource type 'ODataDemo.Product'.");
        }
        public void ReadResource_ThrowsODataException_EntityTypeNotInModel()
        {
            // Arrange
            var deserializer           = new ODataResourceDeserializer(_deserializerProvider);
            ODataResourceWrapper entry = new ODataResourceWrapper(new ODataResource {
                TypeName = "MissingType"
            });

            // Act & Assert
            Assert.Throws <ODataException>(
                () => deserializer.ReadResource(entry, _productEdmType, _readContext),
                "Cannot find the resource type 'MissingType' in the model.");
        }
        public void CreateResourceInstance_CreatesT_IfNotPatchMode()
        {
            // Arrange
            var deserializer = new ODataResourceDeserializer(_deserializerProvider);
            ODataDeserializerContext readContext = new ODataDeserializerContext
            {
                Model        = _readContext.Model,
                ResourceType = typeof(Product)
            };

            // Act & Assert
            Assert.IsType <Product>(deserializer.CreateResourceInstance(_productEdmType, readContext));
        }
        public void ApplyNestedProperty_ThrowsODataException_NavigationPropertyNotfound()
        {
            // Arrange
            var deserializer = new ODataResourceDeserializer(_deserializerProvider);
            ODataNestedResourceInfoWrapper resourceInfoWrapper = new ODataNestedResourceInfoWrapper(new ODataNestedResourceInfo {
                Name = "SomeProperty"
            });

            // Act & Assert
            Assert.Throws <ODataException>(
                () => deserializer.ApplyNestedProperty(42, resourceInfoWrapper, _productEdmType, _readContext),
                "Cannot find nested property 'SomeProperty' on the resource type 'ODataDemo.Product'.");
        }
        public void ReadResource_ThrowsArgument_ModelMissingFromReadContext()
        {
            // Arrange
            var deserializer = new ODataResourceDeserializer(_deserializerProvider);
            ODataResourceWrapper resourceWrapper = new ODataResourceWrapper(new ODataResource {
                TypeName = _supplierEdmType.FullName()
            });

            // Act & Assert
            Assert.ThrowsArgument(
                () => deserializer.ReadResource(resourceWrapper, _productEdmType, new ODataDeserializerContext()),
                "readContext",
                "The EDM model is missing on the read context. The model is required on the read context to deserialize the payload.");
        }
        public void ApplyStructuralProperty_SetsProperty()
        {
            // Arrange
            var           deserializer = new ODataResourceDeserializer(_deserializerProvider);
            Product       product      = new Product();
            ODataProperty property     = new ODataProperty {
                Name = "ID", Value = 42
            };

            // Act
            deserializer.ApplyStructuralProperty(product, property, _productEdmType, _readContext);

            // Assert
            Assert.Equal(42, product.ID);
        }
        public void Read_ThrowsArgument_EntitysetMissing()
        {
            // Arrange
            var deserializer = new ODataResourceDeserializer(_deserializerProvider);
            ODataDeserializerContext readContext = new ODataDeserializerContext
            {
                Path         = new ODataPath(),
                Model        = _edmModel,
                ResourceType = typeof(Product)
            };

            // Act & Assert
            Assert.Throws <SerializationException>(
                () => deserializer.Read(ODataTestUtil.GetMockODataMessageReader(), typeof(Product), readContext),
                "The related entity set or singleton cannot be found from the OData path. The related entity set or singleton is required to deserialize the payload.");
        }
        public void ReadResource_ThrowsSerializationException_TypeCannotBeDeserialized()
        {
            // Arrange
            Mock <ODataDeserializerProvider> deserializerProvider = new Mock <ODataDeserializerProvider>();

            deserializerProvider.Setup(d => d.GetEdmTypeDeserializer(It.IsAny <IEdmTypeReference>())).Returns <ODataEdmTypeDeserializer>(null);
            var deserializer = new ODataResourceDeserializer(deserializerProvider.Object);
            ODataResourceWrapper resourceWrapper = new ODataResourceWrapper(new ODataResource {
                TypeName = _supplierEdmType.FullName()
            });

            // Act & Assert
            Assert.Throws <SerializationException>(
                () => deserializer.ReadResource(resourceWrapper, _productEdmType, _readContext),
                "'ODataDemo.Supplier' cannot be deserialized using the ODataMediaTypeFormatter.");
        }
        public void ApplyNestedProperty_ThrowsODataException_WhenPatchingCollectionNavigationProperty()
        {
            // Arrange
            var deserializer = new ODataResourceDeserializer(_deserializerProvider);
            ODataNestedResourceInfoWrapper resourceInfoWrapper = new ODataNestedResourceInfoWrapper(new ODataNestedResourceInfo {
                Name = "Products"
            });

            resourceInfoWrapper.NestedItems.Add(new ODataResourceSetWrapper(new ODataResourceSet()));
            _readContext.ResourceType = typeof(Delta <Supplier>);

            // Act & Assert
            Assert.Throws <ODataException>(
                () => deserializer.ApplyNestedProperty(42, resourceInfoWrapper, _supplierEdmType, _readContext),
                "Cannot apply PATCH to navigation property 'Products' on entity type 'ODataDemo.Supplier'.");
        }
        public void Read_ThrowsArgument_ODataPathMissing_ForEntity()
        {
            // Arrange
            var deserializer = new ODataResourceDeserializer(_deserializerProvider);
            ODataDeserializerContext readContext = new ODataDeserializerContext
            {
                Model        = _edmModel,
                ResourceType = typeof(Product)
            };

            // Act & Assert
            Assert.ThrowsArgument(
                () => deserializer.Read(ODataTestUtil.GetMockODataMessageReader(), typeof(Product), readContext),
                "readContext",
                "The operation cannot be completed because no ODataPath is available for the request.");
        }
        public void GetODataDeserializer_Resource_ForComplex()
        {
            // Arrange
            HttpRequestMessage request = new HttpRequestMessage();

            request.EnableHttpDependencyInjectionSupport(_edmModel);

            // Act
            ODataDeserializer deserializer = _deserializerProvider.GetODataDeserializer(
                typeof(ODataResourceDeserializerTests.Address), request);

            // Assert
            Assert.NotNull(deserializer);
            ODataResourceDeserializer complexDeserializer = Assert.IsType <ODataResourceDeserializer>(deserializer);

            Assert.Equal(deserializer.ODataPayloadKind, ODataPayloadKind.Resource);
            Assert.Equal(complexDeserializer.DeserializerProvider, _deserializerProvider);
        }
        public void ReadFromStreamAsync()
        {
            // Arrange
            string content = Resources.ProductRequestEntry;
            ODataResourceDeserializer deserializer = new ODataResourceDeserializer(_deserializerProvider);

            // Act
            Product product = deserializer.Read(GetODataMessageReader(GetODataMessage(content), _edmModel),
                                                typeof(Product), _readContext) as Product;

            // Assert
            Assert.Equal(product.ID, 0);
            Assert.Equal(product.Rating, 4);
            Assert.Equal(product.Price, 2.5m);
            Assert.Equal(product.ReleaseDate, new DateTimeOffset(new DateTime(1992, 1, 1, 0, 0, 0), TimeSpan.Zero));
            Assert.Equal(product.PublishDate, new Date(1997, 7, 1));
            Assert.Null(product.DiscontinuedDate);
        }
        public void CreateResourceInstance_CreatesEdmComplexObject_IfTypeLessMode()
        {
            // Arrange
            var deserializer = new ODataResourceDeserializer(_deserializerProvider);
            ODataDeserializerContext readContext = new ODataDeserializerContext
            {
                Model        = _readContext.Model,
                ResourceType = typeof(IEdmObject)
            };

            // Act
            var result = deserializer.CreateResourceInstance(_addressEdmType, readContext);

            // Assert
            EdmComplexObject resource = Assert.IsType <EdmComplexObject>(result);

            Assert.Equal(_addressEdmType, resource.GetEdmType(), new EdmTypeReferenceEqualityComparer());
        }
        public void CreateResourceInstance_CreatesDeltaWith_ExpectedUpdatableProperties()
        {
            // Arrange
            var deserializer = new ODataResourceDeserializer(_deserializerProvider);
            ODataDeserializerContext readContext = new ODataDeserializerContext
            {
                Model        = _readContext.Model,
                ResourceType = typeof(Delta <Product>)
            };
            var structuralProperties = _productEdmType.StructuralProperties().Select(p => p.Name);

            // Act
            Delta <Product> resource = deserializer.CreateResourceInstance(_productEdmType, readContext) as Delta <Product>;

            // Assert
            Assert.NotNull(resource);
            Assert.Equal(structuralProperties, resource.GetUnchangedPropertyNames());
        }
        public void ReadResource_CanReadDatTimeRelatedProperties()
        {
            // Arrange
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();

            builder.EntityType <MyCustomer>().Namespace = "NS";
            IEdmModel model = builder.GetEdmModel();

            IEdmEntityTypeReference vipCustomerTypeReference = model.GetEdmTypeReference(typeof(MyCustomer)).AsEntity();

            var deserializer = new ODataResourceDeserializer(_deserializerProvider);

            ODataResource resource = new ODataResource
            {
                Properties = new[]
                {
                    new ODataProperty {
                        Name = "Id", Value = 121
                    },
                    new ODataProperty {
                        Name = "Birthday", Value = new Date(2015, 12, 12)
                    },
                    new ODataProperty {
                        Name = "ReleaseTime", Value = new TimeOfDay(1, 2, 3, 4)
                    },
                },
                TypeName = "NS.MyCustomer"
            };

            ODataDeserializerContext readContext = new ODataDeserializerContext {
                Model = model
            };
            ODataResourceWrapper resourceWrapper = new ODataResourceWrapper(resource);

            // Act
            var customer = deserializer.ReadResource(resourceWrapper, vipCustomerTypeReference, readContext) as MyCustomer;

            // Assert
            Assert.NotNull(customer);
            Assert.Equal(121, customer.Id);
            Assert.Equal(new DateTime(2015, 12, 12), customer.Birthday);
            Assert.Equal(new TimeSpan(0, 1, 2, 3, 4), customer.ReleaseTime);
        }
예제 #22
0
        public void CanDeserializerSingletonPayloadFromStream()
        {
            // Arrange
            const string payload = "{" +
                                   "\"@odata.context\":\"http://localhost/odata/$metadata#CEO\"," +
                                   "\"EmployeeId\":789," +
                                   "\"EmployeeName\":\"John Hark\"}";

            ODataResourceDeserializer deserializer = new ODataResourceDeserializer(_deserializerProvider);

            // Act
            EmployeeModel employee = deserializer.Read(
                GetODataMessageReader(payload),
                typeof(EmployeeModel),
                _readContext) as EmployeeModel;

            // Assert
            Assert.NotNull(employee);
            Assert.Equal(789, employee.EmployeeId);
            Assert.Equal("John Hark", employee.EmployeeName);
        }
        public void ReadResource_DispatchesToRightDeserializer_IfEntityTypeNameIsDifferent()
        {
            // Arrange
            Mock <ODataEdmTypeDeserializer>  supplierDeserializer = new Mock <ODataEdmTypeDeserializer>(ODataPayloadKind.Resource);
            Mock <ODataDeserializerProvider> deserializerProvider = new Mock <ODataDeserializerProvider>();
            var deserializer = new ODataResourceDeserializer(deserializerProvider.Object);
            ODataResourceWrapper resourceWrapper = new ODataResourceWrapper(new ODataResource {
                TypeName = _supplierEdmType.FullName()
            });

            deserializerProvider.Setup(d => d.GetEdmTypeDeserializer(It.IsAny <IEdmTypeReference>())).Returns(supplierDeserializer.Object);
            supplierDeserializer
            .Setup(d => d.ReadInline(resourceWrapper, It.Is <IEdmTypeReference>(e => _supplierEdmType.Definition == e.Definition), _readContext))
            .Returns(42).Verifiable();

            // Act
            object result = deserializer.ReadResource(resourceWrapper, _productEdmType, _readContext);

            // Assert
            supplierDeserializer.Verify();
            Assert.Equal(42, result);
        }
        public void ReadResource_ThrowsODataException_CannotInstantiateAbstractResourceType()
        {
            // Arrange
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();

            builder.EntityType <BaseType>().Abstract();
            IEdmModel            model           = builder.GetEdmModel();
            var                  deserializer    = new ODataResourceDeserializer(_deserializerProvider);
            ODataResourceWrapper resourceWrapper =
                new ODataResourceWrapper(new ODataResource
            {
                TypeName = "System.Web.OData.Formatter.Deserialization.BaseType"
            });

            // Act & Assert
            Assert.Throws <ODataException>(
                () => deserializer.ReadResource(resourceWrapper, _productEdmType, new ODataDeserializerContext {
                Model = model
            }),
                "An instance of the abstract resource type 'System.Web.OData.Formatter.Deserialization.BaseType' was found. " +
                "Abstract resource types cannot be instantiated.");
        }
        public override object Read(ODataMessageReader messageReader, Type type, ODataDeserializerContext readContext)
        {
            if (messageReader == null)
            {
                throw Error.ArgumentNull("messageReader");
            }

            IEdmAction action = GetAction(readContext);

            Contract.Assert(action != null);

            // Create the correct resource type;
            Dictionary <string, object> payload;

            if (type == typeof(ODataActionParameters))
            {
                payload = new ODataActionParameters();
            }
            else
            {
                payload = new ODataUntypedActionParameters(action);
            }

            ODataParameterReader reader = messageReader.CreateODataParameterReader(action);

            while (reader.Read())
            {
                string parameterName             = null;
                IEdmOperationParameter parameter = null;

                switch (reader.State)
                {
                case ODataParameterReaderState.Value:
                    parameterName = reader.Name;
                    parameter     = action.Parameters.SingleOrDefault(p => p.Name == parameterName);
                    // ODataLib protects against this but asserting just in case.
                    Contract.Assert(parameter != null, String.Format(CultureInfo.InvariantCulture, "Parameter '{0}' not found.", parameterName));
                    if (parameter.Type.IsPrimitive())
                    {
                        payload[parameterName] = reader.Value;
                    }
                    else
                    {
                        ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(parameter.Type);
                        payload[parameterName] = deserializer.ReadInline(reader.Value, parameter.Type, readContext);
                    }
                    break;

                case ODataParameterReaderState.Collection:
                    parameterName = reader.Name;
                    parameter     = action.Parameters.SingleOrDefault(p => p.Name == parameterName);
                    // ODataLib protects against this but asserting just in case.
                    Contract.Assert(parameter != null, String.Format(CultureInfo.InvariantCulture, "Parameter '{0}' not found.", parameterName));
                    IEdmCollectionTypeReference collectionType = parameter.Type as IEdmCollectionTypeReference;
                    Contract.Assert(collectionType != null);
                    ODataCollectionValue        value = ODataCollectionDeserializer.ReadCollection(reader.CreateCollectionReader());
                    ODataCollectionDeserializer collectionDeserializer = (ODataCollectionDeserializer)DeserializerProvider.GetEdmTypeDeserializer(collectionType);
                    payload[parameterName] = collectionDeserializer.ReadInline(value, collectionType, readContext);
                    break;

                case ODataParameterReaderState.Resource:
                    parameterName = reader.Name;
                    parameter     = action.Parameters.SingleOrDefault(p => p.Name == parameterName);
                    Contract.Assert(parameter != null, String.Format(CultureInfo.InvariantCulture, "Parameter '{0}' not found.", parameterName));
                    Contract.Assert(parameter.Type.IsStructured());

                    ODataReader resourceReader = reader.CreateResourceReader();
                    object      item           = resourceReader.ReadResourceOrResourceSet();
                    ODataResourceDeserializer resourceDeserializer = (ODataResourceDeserializer)DeserializerProvider.GetEdmTypeDeserializer(parameter.Type);
                    payload[parameterName] = resourceDeserializer.ReadInline(item, parameter.Type, readContext);
                    break;

                case ODataParameterReaderState.ResourceSet:
                    parameterName = reader.Name;
                    parameter     = action.Parameters.SingleOrDefault(p => p.Name == parameterName);
                    Contract.Assert(parameter != null, String.Format(CultureInfo.InvariantCulture, "Parameter '{0}' not found.", parameterName));

                    IEdmCollectionTypeReference resourceSetType = parameter.Type as IEdmCollectionTypeReference;
                    Contract.Assert(resourceSetType != null);

                    ODataReader resourceSetReader = reader.CreateResourceSetReader();
                    object      feed = resourceSetReader.ReadResourceOrResourceSet();
                    ODataResourceSetDeserializer resourceSetDeserializer = (ODataResourceSetDeserializer)DeserializerProvider.GetEdmTypeDeserializer(resourceSetType);

                    object result = resourceSetDeserializer.ReadInline(feed, resourceSetType, readContext);

                    IEdmTypeReference elementTypeReference = resourceSetType.ElementType();
                    Contract.Assert(elementTypeReference.IsStructured());

                    IEnumerable enumerable = result as IEnumerable;
                    if (enumerable != null)
                    {
                        if (readContext.IsUntyped)
                        {
                            payload[parameterName] = enumerable.ConvertToEdmObject(resourceSetType);
                        }
                        else
                        {
                            Type        elementClrType = EdmLibHelpers.GetClrType(elementTypeReference, readContext.Model);
                            IEnumerable castedResult   =
                                _castMethodInfo.MakeGenericMethod(elementClrType)
                                .Invoke(null, new[] { result }) as IEnumerable;
                            payload[parameterName] = castedResult;
                        }
                    }
                    break;
                }
            }

            return(payload);
        }
        public void ReadResource_CanReadDynamicPropertiesForOpenEntityType()
        {
            // Arrange
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();

            builder.EntityType <SimpleOpenCustomer>();
            builder.EnumType <SimpleEnum>();
            IEdmModel model = builder.GetEdmModel();

            IEdmEntityTypeReference customerTypeReference = model.GetEdmTypeReference(typeof(SimpleOpenCustomer)).AsEntity();

            var deserializer = new ODataResourceDeserializer(_deserializerProvider);

            ODataEnumValue enumValue = new ODataEnumValue("Third", typeof(SimpleEnum).FullName);

            ODataResource[] complexResources =
            {
                new ODataResource
                {
                    TypeName   = typeof(SimpleOpenAddress).FullName,
                    Properties = new[]
                    {
                        // declared properties
                        new ODataProperty {
                            Name = "Street", Value = "Street 1"
                        },
                        new ODataProperty {
                            Name = "City", Value = "City 1"
                        },

                        // dynamic properties
                        new ODataProperty
                        {
                            Name  = "DateTimeProperty",
                            Value = new DateTimeOffset(new DateTime(2014, 5, 6))
                        }
                    }
                },
                new ODataResource
                {
                    TypeName   = typeof(SimpleOpenAddress).FullName,
                    Properties = new[]
                    {
                        // declared properties
                        new ODataProperty {
                            Name = "Street", Value = "Street 2"
                        },
                        new ODataProperty {
                            Name = "City", Value = "City 2"
                        },

                        // dynamic properties
                        new ODataProperty
                        {
                            Name  = "ArrayProperty",
                            Value = new ODataCollectionValue{
                                TypeName = "Collection(Edm.Int32)", Items = new[]{                                         1, 2, 3, 4 }.Cast <object>()
                            }
                        }
                    }
                }
            };

            ODataResource odataResource = new ODataResource
            {
                Properties = new[]
                {
                    // declared properties
                    new ODataProperty {
                        Name = "CustomerId", Value = 991
                    },
                    new ODataProperty {
                        Name = "Name", Value = "Name #991"
                    },

                    // dynamic properties
                    new ODataProperty {
                        Name = "GuidProperty", Value = new Guid("181D3A20-B41A-489F-9F15-F91F0F6C9ECA")
                    },
                    new ODataProperty {
                        Name = "EnumValue", Value = enumValue
                    },
                },
                TypeName = typeof(SimpleOpenCustomer).FullName
            };

            ODataDeserializerContext readContext = new ODataDeserializerContext()
            {
                Model = model
            };

            ODataResourceWrapper topLevelResourceWrapper = new ODataResourceWrapper(odataResource);

            ODataNestedResourceInfo resourceInfo = new ODataNestedResourceInfo
            {
                IsCollection = true,
                Name         = "CollectionProperty"
            };
            ODataNestedResourceInfoWrapper resourceInfoWrapper = new ODataNestedResourceInfoWrapper(resourceInfo);
            ODataResourceSetWrapper        resourceSetWrapper  = new ODataResourceSetWrapper(new ODataResourceSet
            {
                TypeName = String.Format("Collection({0})", typeof(SimpleOpenAddress).FullName)
            });

            foreach (var complexResource in complexResources)
            {
                resourceSetWrapper.Resources.Add(new ODataResourceWrapper(complexResource));
            }
            resourceInfoWrapper.NestedItems.Add(resourceSetWrapper);
            topLevelResourceWrapper.NestedResourceInfos.Add(resourceInfoWrapper);

            // Act
            SimpleOpenCustomer customer = deserializer.ReadResource(topLevelResourceWrapper, customerTypeReference, readContext)
                                          as SimpleOpenCustomer;

            // Assert
            Assert.NotNull(customer);

            // Verify the declared properties
            Assert.Equal(991, customer.CustomerId);
            Assert.Equal("Name #991", customer.Name);

            // Verify the dynamic properties
            Assert.NotNull(customer.CustomerProperties);
            Assert.Equal(3, customer.CustomerProperties.Count());
            Assert.Equal(new Guid("181D3A20-B41A-489F-9F15-F91F0F6C9ECA"), customer.CustomerProperties["GuidProperty"]);
            Assert.Equal(SimpleEnum.Third, customer.CustomerProperties["EnumValue"]);

            // Verify the dynamic collection property
            var collectionValues = Assert.IsType <List <SimpleOpenAddress> >(customer.CustomerProperties["CollectionProperty"]);

            Assert.NotNull(collectionValues);
            Assert.Equal(2, collectionValues.Count());

            Assert.Equal(new DateTimeOffset(new DateTime(2014, 5, 6)), collectionValues[0].Properties["DateTimeProperty"]);
            Assert.Equal(new List <int> {
                1, 2, 3, 4
            }, collectionValues[1].Properties["ArrayProperty"]);
        }