diff --git a/Moq.Dapper.Test/DapperQueryTest.cs b/Moq.Dapper.Test/DapperQueryTest.cs index 666b7a0..9564596 100644 --- a/Moq.Dapper.Test/DapperQueryTest.cs +++ b/Moq.Dapper.Test/DapperQueryTest.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Data; +using System.IO; using System.Linq; using System.Numerics; using System.Security.Cryptography; @@ -282,6 +284,42 @@ public void QueryFirstOrDefaultString() Assert.That(actual, Is.Null); } + [Test] + public void SetupDapper_SetForKnownNonPrimitiveTypes_QueryShouldBeAbleToReturnMockedCollections() + { + TestQueryWithKnownNonPrimitiveTypes(new List { FileMode.Open, FileMode.Create }); + TestQueryWithKnownNonPrimitiveTypes(new List { FileMode.Open, null }); + TestQueryWithKnownNonPrimitiveTypes(new List { DateTime.Now, DateTime.Now.AddDays(1) }); + TestQueryWithKnownNonPrimitiveTypes(new List { null, DateTime.Now.AddDays(1) }); + TestQueryWithKnownNonPrimitiveTypes(new List { DateTimeOffset.UtcNow, DateTimeOffset.Now}); + TestQueryWithKnownNonPrimitiveTypes(new List { null, DateTimeOffset.UtcNow }); + TestQueryWithKnownNonPrimitiveTypes(new List { 1.234m, 4.65m }); + TestQueryWithKnownNonPrimitiveTypes(new List { null, 4.65m }); + TestQueryWithKnownNonPrimitiveTypes(new List { Guid.NewGuid(), Guid.NewGuid() }); + TestQueryWithKnownNonPrimitiveTypes(new List { Guid.NewGuid(), null }); + TestQueryWithKnownNonPrimitiveTypes(new List { "One", "Two" }); + TestQueryWithKnownNonPrimitiveTypes(new List { "One", null }); + TestQueryWithKnownNonPrimitiveTypes(new List { TimeSpan.MinValue, TimeSpan.MaxValue }); + TestQueryWithKnownNonPrimitiveTypes(new List { TimeSpan.MinValue, null }); + TestQueryWithKnownNonPrimitiveTypes(new List { new byte[] { 144, 27, 113, 141, 6, 167, 63, 45, 89, 186, 226, 225, 155, 20, 175, 86 }, new byte[] { 144, 27, 113, 141, 6, 167, 63, 45, 89, 186, 226, 225, 155, 20, 175, 87 }}); + TestQueryWithKnownNonPrimitiveTypes(new List { new byte[] { 144, 27, 113, 141, 6, 167, 63, 45, 89, 186, 226, 225, 155, 20, 175, 86 }, null }); + } + + #region Private members + private void TestQueryWithKnownNonPrimitiveTypes(IEnumerable expected) + { + var connection = new Mock(); + + connection.SetupDapper(c => c.Query(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Returns(expected); + + var actual = connection.Object.Query(""); + + Assert.That(actual.Count, Is.EqualTo(expected.Count())); + Assert.That(actual, Is.EquivalentTo(expected)); + } + #endregion + public class ComplexType { public enum EnumType diff --git a/Moq.Dapper/EnumerableExtensions.cs b/Moq.Dapper/EnumerableExtensions.cs index d10c0d3..6ae8ac1 100644 --- a/Moq.Dapper/EnumerableExtensions.cs +++ b/Moq.Dapper/EnumerableExtensions.cs @@ -11,37 +11,28 @@ public static class EnumerableExtensions internal static DataTable ToDataTable(this IEnumerable results, Type tableType) { var dataTable = new DataTable(); - - if (tableType.IsPrimitive || tableType == typeof(string)) + + var underlyingType = GetDataColumnType(tableType); + + if (IsADapperQuerySupportedType(underlyingType)) { - dataTable.Columns.Add(); + dataTable.Columns.Add(new DataColumn("Column1", underlyingType)); foreach (var element in results) - dataTable.Rows.Add(element); + { + if(element == null) + { + dataTable.Rows.Add(DBNull.Value); + } + else + { + dataTable.Rows.Add(element); + } + } + } else { - bool IsNullable(Type t) => - t.IsGenericType && - t.GetGenericTypeDefinition() == typeof(Nullable<>); - - Type GetDataColumnType(Type source) => - IsNullable(source) ? - Nullable.GetUnderlyingType(source) : - source; - - bool IsMatchingType(Type t) => - t.IsPrimitive || - t.IsEnum || - t == typeof(DateTime) || - t == typeof(DateTimeOffset) || - t == typeof(decimal) || - t == typeof(BigInteger) || - t == typeof(Guid) || - t == typeof(string) || - t == typeof(TimeSpan) || - t == typeof(byte[]); - var properties = tableType.GetProperties(). Where @@ -61,6 +52,32 @@ bool IsMatchingType(Type t) => foreach (var element in results) dataTable.Rows.Add(valuesFactory.Select(getValue => getValue(element)).ToArray()); } + + bool IsNullable(Type t) => + t.IsGenericType && + t.GetGenericTypeDefinition() == typeof(Nullable<>); + + Type GetDataColumnType(Type source) => + IsNullable(source) ? + Nullable.GetUnderlyingType(source) : + source; + + bool IsADapperQuerySupportedType(Type t) => + t.IsPrimitive || + t.IsEnum || + t == typeof(DateTime) || + t == typeof(DateTimeOffset) || + t == typeof(decimal) || + t == typeof(Guid) || + t == typeof(string) || + t == typeof(TimeSpan) || + t == typeof(byte[]); + + //Dapper does not list BigInteger in it's type map. + //So, Query returns 0 for every BigInteger in Response. + bool IsMatchingType(Type t) => + IsADapperQuerySupportedType(t) || + t == typeof(BigInteger); return dataTable; }