From e0aa61377bbc802e5efd5e444dc44128c18554b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karsten=20K=C3=BCpper?= Date: Thu, 28 Nov 2013 15:46:48 +0100 Subject: [PATCH 1/3] improve support for Arrays and add Tests for Arrays --- Slapper.AutoMapper.Tests/ArrayTests.cs | 156 +++++++++++++++++++++++ Slapper.AutoMapper/Slapper.AutoMapper.cs | 28 ++-- 2 files changed, 172 insertions(+), 12 deletions(-) diff --git a/Slapper.AutoMapper.Tests/ArrayTests.cs b/Slapper.AutoMapper.Tests/ArrayTests.cs index 77d56d3..af4bb65 100644 --- a/Slapper.AutoMapper.Tests/ArrayTests.cs +++ b/Slapper.AutoMapper.Tests/ArrayTests.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using NUnit.Framework; namespace Slapper.Tests @@ -22,6 +23,13 @@ public class PersonWithProperties public string[] FavoriteFoods { get; set; } } + public class Department + { + public int Id { get; set; } + public string Name { get; set; } + public PersonWithProperties[] Staff { get; set; } + } + [Test] public void Can_Map_Null_Values_To_Null_Arrays() { @@ -77,5 +85,153 @@ public void Can_Map_Array_Values_To_Arrays() Assert.That( customer.LastName == lastName ); Assert.That( customer.FavoriteFoods == favoriteFoods ); } + + [Test] + public void Can_Map_Multiple_Dictionaries_To_Arrays() + { + // Arrange + const int id = 1; + const string name = "IT"; + const int firstEmployeeId = 1; + const string firstEmployeeLastName = "Smith"; + const int secondEmployeeId = 2; + const string secondEmployeeLastName = "Doe"; + + var firstDictionary = new Dictionary + { + {"Id", id}, + {"Name", name}, + {"Staff_Id", firstEmployeeId}, + {"Staff_LastName", firstEmployeeLastName} + }; + + var secondDictionary = new Dictionary + { + {"Id", id}, + {"Name", name}, + {"Staff_Id", secondEmployeeId}, + {"Staff_LastName", secondEmployeeLastName} + }; + + // Act + var department = + AutoMapper.Map(new List> {firstDictionary, secondDictionary}).Single(); + + // Assert + Assert.That(department.Id == id); + Assert.That(department.Name == name); + Assert.That(department.Staff.Count() == 2); + Assert.That(department.Staff[0].Id == firstEmployeeId); + Assert.That(department.Staff[0].LastName == firstEmployeeLastName); + Assert.That(department.Staff[1].Id == secondEmployeeId); + Assert.That(department.Staff[1].LastName == secondEmployeeLastName); + } + + public class Customer + { + public int CustomerId; + public string FirstName; + public string LastName; + public Order[] Orders; + } + + public class Order + { + public int OrderId; + public decimal OrderTotal; + public OrderDetail[] OrderDetails; + } + + public class OrderDetail + { + public int OrderDetailId; + public decimal OrderDetailTotal; + } + + [Test] + public void I_Can_Map_Nested_Types_With_Multiple_Identifiers_And_Resolve_Duplicate_Entries_Properly() + { + // Arrange + var dictionary = new Dictionary + { + { "CustomerId", 1 }, + { "FirstName", "Bob" }, + { "LastName", "Smith" }, + { "Orders_OrderId", 1 }, + { "Orders_OrderTotal", 50.50m }, + { "Orders_OrderDetails_OrderDetailId", 1 }, + { "Orders_OrderDetails_OrderDetailTotal", 25.00m } + }; + + var dictionary2 = new Dictionary + { + { "CustomerId", 1 }, + { "FirstName", "Bob" }, + { "LastName", "Smith" }, + { "Orders_OrderId", 1 }, + { "Orders_OrderTotal", 50.50m }, + { "Orders_OrderDetails_OrderDetailId", 2 }, + { "Orders_OrderDetails_OrderDetailTotal", 25.50m } + }; + + var dictionary3 = new Dictionary + { + { "CustomerId", 1 + 1 }, + { "FirstName", "Bob" }, + { "LastName", "Smith" }, + { "Orders_OrderId", 1 }, + { "Orders_OrderTotal", 50.50m }, + { "Orders_OrderDetails_OrderDetailId", 2 }, + { "Orders_OrderDetails_OrderDetailTotal", 25.50m } + }; + + var list = new List> { dictionary, dictionary2, dictionary3 }; + + // Act + var customers = Slapper.AutoMapper.Map(list).ToArray(); + + // Assert + + Assert.That(customers.Count() == 2); + Assert.That(customers.FirstOrDefault().Orders.Length == 1); // There should only be a single Order + Assert.That(customers.FirstOrDefault().Orders.FirstOrDefault().OrderDetails.Length == 2); // There should be two OrderDetails + } + + //[Test] + //public void Can_Detect_Duplicate_Parent_Members_And_Properly_Instantiate_The_Object_Only_Once() + //{ + // // Arrange + // const int id = 1; + // const string name = "IT"; + // const int firstEmployeeId = 1; + // const string firstEmployeeLastName = "Smith"; + + // var firstDictionary = new Dictionary + // { + // {"Id", id}, + // {"Name", name}, + // {"Staff_Id", firstEmployeeId}, + // {"Staff_LastName", firstEmployeeLastName} + // }; + + // var secondDictionary = new Dictionary + // { + // {"Id", id}, + // {"Name", name}, + // {"Staff_Id", firstEmployeeId}, + // {"Staff_LastName", firstEmployeeLastName} + // }; + + // // Act + // var department = + // AutoMapper.Map(new List> { firstDictionary, secondDictionary }).Single(); + + // // Assert + // Assert.That(department.Id == id); + // Assert.That(department.Name == name); + // Assert.That(department.Staff.Count() == 2); + // Assert.That(department.Staff[0].Id == firstEmployeeId); + // Assert.That(department.Staff[0].LastName == firstEmployeeLastName); + //} } } \ No newline at end of file diff --git a/Slapper.AutoMapper/Slapper.AutoMapper.cs b/Slapper.AutoMapper/Slapper.AutoMapper.cs index 93c36ce..171c5c2 100644 --- a/Slapper.AutoMapper/Slapper.AutoMapper.cs +++ b/Slapper.AutoMapper/Slapper.AutoMapper.cs @@ -111,7 +111,7 @@ public static IEnumerable MapDynamic( IEnumerable dynamicListOfPro var dictionary = dynamicListOfProperties.Select( dynamicItem => dynamicItem as IDictionary ).ToList(); - if ( dictionary == null ) + if ( dictionary == null ) // I can't think of any case where this could possibly happen throw new ArgumentException( "Object types cannot be converted to an IDictionary", "dynamicListOfProperties" ); if ( dictionary.Count == 0 || dictionary[ 0 ] == null ) @@ -1120,7 +1120,7 @@ public static object MapCollection( Type type, IDictionary dicti { if ( isArray ) { - var arrayList = new ArrayList { instanceToAddToCollectionInstance }; + var arrayList = new ArrayList((ICollection) instance) {instanceToAddToCollectionInstance}; instance = arrayList.ToArray( type ); } @@ -1133,19 +1133,23 @@ public static object MapCollection( Type type, IDictionary dicti } else { - MethodInfo containsMethod = listType.GetMethod( "Contains" ); - - var alreadyContainsInstance = ( bool ) containsMethod.Invoke( instance, new[] { instanceToAddToCollectionInstance } ); - - if ( alreadyContainsInstance == false ) + if (isArray) { - if ( isArray ) - { - var arrayList = new ArrayList( ( ICollection ) instance ); + var arrayList = new ArrayList((ICollection)instance); - instance = arrayList.ToArray( type ); + if ( !arrayList.Contains(instanceToAddToCollectionInstance) ) + { + arrayList.Add(instanceToAddToCollectionInstance); } - else + instance = arrayList.ToArray(type); + } + else + { + MethodInfo containsMethod = listType.GetMethod( "Contains" ); + + var alreadyContainsInstance = ( bool ) containsMethod.Invoke( instance, new[] { instanceToAddToCollectionInstance } ); + + if ( alreadyContainsInstance == false ) { MethodInfo addMethod = listType.GetMethod( "Add" ); From 7114a59f111c6f8c407659f8f1046102e1fec508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karsten=20K=C3=BCpper?= Date: Thu, 28 Nov 2013 15:47:36 +0100 Subject: [PATCH 2/3] improve test code coverage --- Slapper.AutoMapper.Tests/MapDynamicTests.cs | 43 ++++++++++++++++++- .../MappingToGuidTests.cs | 20 +++++++++ Slapper.AutoMapper.Tests/Slapper.Tests.csproj | 3 ++ 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/Slapper.AutoMapper.Tests/MapDynamicTests.cs b/Slapper.AutoMapper.Tests/MapDynamicTests.cs index d3bed84..80b28c0 100644 --- a/Slapper.AutoMapper.Tests/MapDynamicTests.cs +++ b/Slapper.AutoMapper.Tests/MapDynamicTests.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Dynamic; using System.Linq; using NUnit.Framework; @@ -22,6 +23,46 @@ public class Order public decimal OrderTotal; } + [Test] + public void Returns_Empty_List_For_Null_Dictionary() + { + // Arrange + + // Act + var result = Slapper.AutoMapper.MapDynamic(null); + + // Assert + Assert.NotNull(result); + Assert.That(!result.Any()); + } + + [Test] + public void Returns_Null_For_Reference_Types() + { + // Arrange + object nullDictionary = null; + + // Act + var result = Slapper.AutoMapper.MapDynamic(nullDictionary); + + // Assert + Assert.IsNull(result); + } + + [Test] + public void Returns_Zero_For_Numeric_Value_Types() + { + // Arrange + object nullDictionary = null; + + // Act + var result = Slapper.AutoMapper.MapDynamic(nullDictionary); + + // Assert + Assert.IsNotNull(result); + Assert.That(result == 0); + } + [Test] public void Can_Handle_Mapping_A_Single_Dynamic_Object() { diff --git a/Slapper.AutoMapper.Tests/MappingToGuidTests.cs b/Slapper.AutoMapper.Tests/MappingToGuidTests.cs index 10207a9..2c6dfeb 100644 --- a/Slapper.AutoMapper.Tests/MappingToGuidTests.cs +++ b/Slapper.AutoMapper.Tests/MappingToGuidTests.cs @@ -129,6 +129,26 @@ public void Can_Map_Guid_String_Values_To_Guid_Properties() Assert.That( Equals( customer.UniqueId, uniqueId ) ); // This is what we are testing } + [Test] + public void Can_Map_Guid_Byte_Array_Values_To_Guid_Properties() + { + // Arrange + const int id = 1; + Guid uniqueId = Guid.NewGuid(); + + dynamic dynamicPerson = new ExpandoObject(); + dynamicPerson.Id = id; + dynamicPerson.UniqueId = uniqueId.ToByteArray(); // This is what we are testing + + // Act + PersonWithProperties customer = Slapper.AutoMapper.MapDynamic(dynamicPerson); + + // Assert + Assert.NotNull(customer); + Assert.That(customer.Id == id); + Assert.That(Equals(customer.UniqueId, uniqueId)); // This is what we are testing + } + [Test] public void Can_Map_Null_Values_To_Guid_Fields() { diff --git a/Slapper.AutoMapper.Tests/Slapper.Tests.csproj b/Slapper.AutoMapper.Tests/Slapper.Tests.csproj index ebe2552..6834426 100644 --- a/Slapper.AutoMapper.Tests/Slapper.Tests.csproj +++ b/Slapper.AutoMapper.Tests/Slapper.Tests.csproj @@ -69,6 +69,9 @@ Slapper + + +