Skip to content

Commit

Permalink
Merge pull request MapsterMapper#6 from chaowlert/unit-test
Browse files Browse the repository at this point in the history
Unit tests for primitive types & complex type support
  • Loading branch information
eswann committed Mar 4, 2015
2 parents 02f7109 + b0be91b commit abd0fe7
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 7 deletions.
5 changes: 4 additions & 1 deletion src/Mapster.Tests/Classes/Address.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
namespace Mapster.Tests.Classes
using System.ComponentModel.DataAnnotations.Schema;

namespace Mapster.Tests.Classes
{
[ComplexType]
public class Address
{
public string Street { get; set; }
Expand Down
7 changes: 7 additions & 0 deletions src/Mapster.Tests/Classes/Customer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,11 @@ public class Customer
public string Surname { get; set; }
public Address Address { get; set; }
}

public class CustomerDTO
{
public int Id { get; set; }
public string Name { get; set; }
public string Address_Country { get; set; }
}
}
7 changes: 7 additions & 0 deletions src/Mapster.Tests/Classes/Product.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ public class Order
public Customer Customer { get; set; }
}

public class ProductDTO
{
public Guid Id { get; set; }
public string Title { get; set; }
public string CreatedUserName { get; set; }
}

public class ProductListDTO
{
public Guid Id { get; set; }
Expand Down
2 changes: 2 additions & 0 deletions src/Mapster.Tests/Mapster.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
<HintPath>..\packages\Should.1.1.20\lib\Should.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
</ItemGroup>
<Choose>
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
Expand All @@ -62,6 +63,7 @@
<Compile Include="Classes\Product.cs" />
<Compile Include="Classes\TypeTestClass.cs" />
<Compile Include="WhenAddingCustomMappings.cs" />
<Compile Include="WhenAddingPrimitiveTypes.cs" />
<Compile Include="WhenHandlingUnmappedMembers.cs" />
<Compile Include="WhenExplicitMappingRequired.cs" />
<Compile Include="WhenMappingConditionally.cs" />
Expand Down
83 changes: 83 additions & 0 deletions src/Mapster.Tests/WhenAddingPrimitiveTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System;
using NUnit.Framework;
using Should;

namespace Mapster.Tests
{
[TestFixture]
public class WhenAddingPrimitiveTypes
{
[TearDown]
public void TearDown()
{
TypeAdapterConfig.GlobalSettings.PrimitiveTypes.Clear();
}

[Test]
public void No_Primitive_Uri_Should_Throw()
{
TypeAdapter.ClearCache();
var sourceUri = new Uri("http:https://example.com");

var exception = Assert.Throws<ArgumentNullException>(() => TypeAdapter.Adapt<Uri, Uri>(sourceUri));
Console.WriteLine(exception.Message);

exception.ParamName.ShouldEqual("con");
}

[Test]
public void Set_Primitive_Uri_Success()
{
TypeAdapter.ClearCache();
TypeAdapterConfig.GlobalSettings.PrimitiveTypes.Add(typeof(Uri));

var sourceUri = new Uri("http:https://example.com");
var targetUri = TypeAdapter.Adapt<Uri, Uri>(sourceUri);

targetUri.ShouldEqual(sourceUri);
}

[Test]
public void No_Primitive_Uri_Property_Should_Throw()
{
TypeAdapterConfig<SimplePoco, SimplePoco>.Clear();
var sourceDto = new SimplePoco
{
Id = 1,
Website = new Uri("http:https://example.com"),
};

var exception = Assert.Throws<InvalidOperationException>(() => TypeAdapter.Adapt<SimplePoco, SimplePoco>(sourceDto));
Console.WriteLine(exception.Message);

var innerException = exception.InnerException;
innerException.ShouldBeType<ArgumentNullException>();
((ArgumentNullException)innerException).ParamName.ShouldEqual("con");
}

[Test]
public void Set_Primitive_Uri_Property_Success()
{
TypeAdapterConfig<SimplePoco, SimplePoco>.Clear();
TypeAdapterConfig.GlobalSettings.PrimitiveTypes.Add(typeof(Uri));

var sourceDto = new SimplePoco
{
Id = 1,
Website = new Uri("http:https://example.com"),
};
var targetDto = TypeAdapter.Adapt<SimplePoco, SimplePoco>(sourceDto);

targetDto.Website.ShouldEqual(sourceDto.Website);
}
#region TestClasses

public class SimplePoco
{
public int Id { get; set; }
public Uri Website { get; set; }
}

#endregion
}
}
14 changes: 14 additions & 0 deletions src/Mapster.Tests/WhenFlattening.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ public class D
public decimal BClassTotal { get; set; }
}

public class E
{
public decimal BClass_Total { get; set; }
}

#endregion

[TestFixture]
Expand All @@ -53,5 +58,14 @@ public void PropertyTest()
Assert.IsNotNull(d);
Assert.IsTrue(d.BClassTotal == 250);
}

[Test]
public void PropertyTest_NameWithUnderscore()
{
var e = ClassAdapter<C, E>.Adapt(new C { BClass = new B { Total = 250 } });

Assert.IsNotNull(e);
Assert.IsTrue(e.BClass_Total == 250);
}
}
}
47 changes: 47 additions & 0 deletions src/Mapster.Tests/WhenProjecting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using Mapster.Tests.Classes;
using NUnit.Framework;
using Should;

namespace Mapster.Tests
{
Expand Down Expand Up @@ -256,6 +257,52 @@ public void TestMaxDepthListProperty()
Assert.IsTrue(bList[0].Source.First().Source.Source == null);
}

[Test]
public void TestComplexTypeMapping()
{
var customers = new[]
{
new Customer {Id = 1, Name = "CustomerA", Address = new Address {Country = "CountryA"}},
new Customer {Id = 1, Name = "CustomerB", Address = new Address {Country = "CountryB"}},
};

var resultQuery = customers.AsQueryable().Project().To<CustomerDTO>();
var expectedQuery = from srcCustomer0 in customers.AsQueryable()
select new CustomerDTO
{
Id = srcCustomer0.Id,
Name = srcCustomer0.Name,
Address_Country = srcCustomer0.Address.Country,
};
resultQuery.ToString().ShouldEqual(expectedQuery.ToString());

var result = resultQuery.ToList().Last();
result.Address_Country.ShouldEqual(customers.Last().Address.Country);
}

[Test]
public void TestPocoTypeMapping()
{
var products = new[]
{
new Product {Id = Guid.NewGuid(), Title = "ProductA", CreatedUser = new User {Name = "UserA"}},
new Product {Id = Guid.NewGuid(), Title = "ProductB", CreatedUser = null},
};

var resultQuery = products.AsQueryable().Project().To<ProductDTO>();
var expectedQuery = from srcProduct0 in products.AsQueryable()
select new ProductDTO
{
Id = srcProduct0.Id,
Title = srcProduct0.Title,
CreatedUserName = srcProduct0.CreatedUser == null ? null : srcProduct0.CreatedUser.Name,
};
resultQuery.ToString().ShouldEqual(expectedQuery.ToString());

var result = resultQuery.ToList().Last();
result.CreatedUserName.ShouldBeNull();
}

private List<Product> GetProducts()
{
var user = new User()
Expand Down
4 changes: 4 additions & 0 deletions src/Mapster/TypeAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ private static FastInvokeHandler GetAdapter(Type sourceType, Type destinationTyp
}
}

internal static void ClearCache()
{
_cache.Clear();
}

private static FastInvokeHandler GetAdapter<TSource, TDestination>(bool hasDestination = false)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Mapster/TypeAdapterGlobalSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ public class TypeAdapterGlobalSettings

public bool AllowImplicitDestinationInheritance;

public readonly HashSet<Type> PrimitiveType = new HashSet<Type>();
public readonly HashSet<Type> PrimitiveTypes = new HashSet<Type>();
}
}
8 changes: 4 additions & 4 deletions src/Mapster/Utils/ProjectionExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ private static BaseProjectionConfig GetCachedConfig(Type sourceType, Type destin
return Expression.Bind(destinationProperty, newMemberExpression);
}

var nullCheck = Expression.Equal(Expression.Property(parameterExpression, sourceProperty), Expression.Constant(null));
var nullCheck = Expression.Equal(Expression.Property(parameterExpression, sourceProperty), Expression.Constant(null, sourceProperty.PropertyType));

var convertExp = Expression.Convert(Expression.Constant(null), destPropertyType);
var convertExp = Expression.Constant(null, destPropertyType);

var conditionExpression = Expression.Condition(nullCheck, convertExp, newMemberExpression);

Expand Down Expand Up @@ -198,12 +198,12 @@ private static BaseProjectionConfig GetCachedConfig(Type sourceType, Type destin
return Expression.Bind(destinationProperty, childExp);
}

var nullCheck = Expression.Equal(Expression.Property(parameterExpression, sourceProperty), Expression.Constant(null));
var nullCheck = Expression.Equal(Expression.Property(parameterExpression, sourceProperty), Expression.Constant(null, sourceProperty.PropertyType));
Expression defaultValueExp;
if (destinationPropertyType.IsValueType && !ReflectionUtils.IsNullable(destinationPropertyType))
defaultValueExp = Expression.Constant(ActivatorExtensions.CreateInstance(destinationPropertyType));
else
defaultValueExp = Expression.Convert(Expression.Constant(null), destinationPropertyType);
defaultValueExp = Expression.Constant(null, destinationPropertyType);
var conditionExpression = Expression.Condition(nullCheck, defaultValueExp, childExp);

return Expression.Bind(destinationProperty, conditionExpression);
Expand Down
2 changes: 1 addition & 1 deletion src/Mapster/Utils/ReflectionUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public static bool IsPrimitiveRoot(this Type type)
|| type == typeof(Guid)
|| type.IsEnum
|| (IsNullable(type) && IsPrimitiveRoot(Nullable.GetUnderlyingType(type)))
|| TypeAdapterConfig.GlobalSettings.PrimitiveType.Contains(type)
|| TypeAdapterConfig.GlobalSettings.PrimitiveTypes.Contains(type)
|| type == typeof(object)
;
}
Expand Down

0 comments on commit abd0fe7

Please sign in to comment.