Commit 8c46aee6 authored by Nick Craver's avatar Nick Craver

Port tests to be both xUnit and dnx raw program compatible

This let's us run the tests much faster and all from Visual Studio,
command line, and Appveyor.

TODO: Flag missing test methods
parent a7ee3092
...@@ -11,3 +11,4 @@ NuGet.exe ...@@ -11,3 +11,4 @@ NuGet.exe
.docstats .docstats
*.ide/ *.ide/
*.lock.json *.lock.json
*.coverage
\ No newline at end of file
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
#if DOTNET5_2
using ApplicationException = System.InvalidOperationException;
#endif
namespace SqlMapper namespace SqlMapper
{ {
...@@ -13,54 +8,36 @@ static class Assert ...@@ -13,54 +8,36 @@ static class Assert
public static void IsEqualTo<T>(this T obj, T other) public static void IsEqualTo<T>(this T obj, T other)
{ {
if (!Equals(obj, other)) Xunit.Assert.Equal(obj, other);
{
throw new ApplicationException($"{obj} should be equals to {other}");
}
} }
public static void IsSequenceEqualTo<T>(this IEnumerable<T> obj, IEnumerable<T> other) public static void IsSequenceEqualTo<T>(this IEnumerable<T> obj, IEnumerable<T> other)
{ {
if (!(obj ?? new T[0]).SequenceEqual(other ?? new T[0])) Xunit.Assert.Equal(obj ?? new T[0], other);
{
throw new ApplicationException($"{obj} should be equals to {other}");
}
} }
public static void Fail() public static void Fail()
{ {
throw new ApplicationException("Expectation failed"); Xunit.Assert.True(false, "Expectation failed");
} }
public static void IsFalse(this bool b) public static void IsFalse(this bool b)
{ {
if (b) Xunit.Assert.False(b);
{
throw new ApplicationException("Expected false");
}
} }
public static void IsTrue(this bool b) public static void IsTrue(this bool b)
{ {
if (!b) Xunit.Assert.True(b);
{
throw new ApplicationException("Expected true");
}
} }
public static void IsNull(this object obj) public static void IsNull(this object obj)
{ {
if (obj != null) Xunit.Assert.Null(obj);
{
throw new ApplicationException("Expected null");
}
} }
public static void IsNotNull(this object obj) public static void IsNotNull(this object obj)
{ {
if (obj == null) Xunit.Assert.NotNull(obj);
{
throw new ApplicationException("Expected not null");
}
} }
} }
} }
...@@ -17,5 +17,8 @@ ...@@ -17,5 +17,8 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<ProduceOutputsOnBuild>True</ProduceOutputsOnBuild> <ProduceOutputsOnBuild>True</ProduceOutputsOnBuild>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" /> <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project> </Project>
\ No newline at end of file
...@@ -171,7 +171,7 @@ insert Posts ([Text],CreationDate, LastChangeDate) values (replicate('x', 2000), ...@@ -171,7 +171,7 @@ insert Posts ([Text],CreationDate, LastChangeDate) values (replicate('x', 2000),
#endif #endif
} }
private static void RunTests<T>(ref int fail, ref int skip, ref int pass, ref int frameworkFail, List<string> failNames) where T : class, new() private static void RunTests<T>(ref int fail, ref int skip, ref int pass, ref int frameworkFail, List<string> failNames) where T : class, IDisposable, new()
{ {
var tester = new T(); var tester = new T();
using (tester as IDisposable) using (tester as IDisposable)
...@@ -193,7 +193,10 @@ private static void RunTests<T>(ref int fail, ref int skip, ref int pass, ref in ...@@ -193,7 +193,10 @@ private static void RunTests<T>(ref int fail, ref int skip, ref int pass, ref in
Console.Write("Running " + method.Name); Console.Write("Running " + method.Name);
try try
{ {
method.Invoke(tester, null); using (var t = new T())
{
method.Invoke(t, null);
}
if (expectFrameworkFail) if (expectFrameworkFail)
{ {
Console.WriteLine(" - was expected to framework-fail, but didn't"); Console.WriteLine(" - was expected to framework-fail, but didn't");
......
using Dapper;
using System;
using System.Data;
using System.Linq;
using Xunit;
#if DOTNET5_2
using IDbCommand = System.Data.Common.DbCommand;
using IDbDataParameter = System.Data.Common.DbParameter;
using IDbConnection = System.Data.Common.DbConnection;
using IDbTransaction = System.Data.Common.DbTransaction;
using IDataReader = System.Data.Common.DbDataReader;
#endif
namespace SqlMapper
{
public partial class Tests
{
[Fact]
public void TestAbstractInheritance()
{
var order = connection.Query<AbstractInheritance.ConcreteOrder>("select 1 Internal,2 Protected,3 [Public],4 Concrete").First();
order.Internal.IsEqualTo(1);
order.ProtectedVal.IsEqualTo(2);
order.Public.IsEqualTo(3);
order.Concrete.IsEqualTo(4);
}
[Fact]
public void TestMultipleConstructors()
{
MultipleConstructors mult = connection.Query<MultipleConstructors>("select 0 A, 'Dapper' b").First();
mult.A.IsEqualTo(0);
mult.B.IsEqualTo("Dapper");
}
[Fact]
public void TestConstructorsWithAccessModifiers()
{
ConstructorsWithAccessModifiers value = connection.Query<ConstructorsWithAccessModifiers>("select 0 A, 'Dapper' b").First();
value.A.IsEqualTo(1);
value.B.IsEqualTo("Dapper!");
}
[Fact]
public void TestNoDefaultConstructor()
{
var guid = Guid.NewGuid();
NoDefaultConstructor nodef = connection.Query<NoDefaultConstructor>("select CAST(NULL AS integer) A1, CAST(NULL AS integer) b1, CAST(NULL AS real) f1, 'Dapper' s1, G1 = @id", new { id = guid }).First();
nodef.A.IsEqualTo(0);
nodef.B.IsEqualTo(null);
nodef.F.IsEqualTo(0);
nodef.S.IsEqualTo("Dapper");
nodef.G.IsEqualTo(guid);
}
[Fact]
public void TestNoDefaultConstructorWithChar()
{
const char c1 = 'ą';
const char c3 = 'ó';
NoDefaultConstructorWithChar nodef = connection.Query<NoDefaultConstructorWithChar>("select @c1 c1, @c2 c2, @c3 c3", new { c1 = c1, c2 = (char?)null, c3 = c3 }).First();
nodef.Char1.IsEqualTo(c1);
nodef.Char2.IsEqualTo(null);
nodef.Char3.IsEqualTo(c3);
}
[Fact]
public void TestNoDefaultConstructorWithEnum()
{
NoDefaultConstructorWithEnum nodef = connection.Query<NoDefaultConstructorWithEnum>("select cast(2 as smallint) E1, cast(5 as smallint) n1, cast(null as smallint) n2").First();
nodef.E.IsEqualTo(ShortEnum.Two);
nodef.NE1.IsEqualTo(ShortEnum.Five);
nodef.NE2.IsEqualTo(null);
}
[Fact]
public void ExplicitConstructors()
{
var rows = connection.Query<_ExplicitConstructors>(@"
declare @ExplicitConstructors table (
Field INT NOT NULL PRIMARY KEY IDENTITY(1,1),
Field_1 INT NOT NULL);
insert @ExplicitConstructors(Field_1) values (1);
SELECT * FROM @ExplicitConstructors"
).ToList();
rows.Count.IsEqualTo(1);
rows[0].Field.IsEqualTo(1);
rows[0].Field_1.IsEqualTo(1);
rows[0].GetWentThroughProperConstructor().IsTrue();
}
class _ExplicitConstructors
{
public int Field { get; set; }
public int Field_1 { get; set; }
private bool WentThroughProperConstructor;
public _ExplicitConstructors() { }
[ExplicitConstructor]
public _ExplicitConstructors(string foo, int bar)
{
WentThroughProperConstructor = true;
}
public bool GetWentThroughProperConstructor()
{
return WentThroughProperConstructor;
}
}
#if EXTERNALS
class NoDefaultConstructorWithBinary
{
public System.Data.Linq.Binary Value { get; set; }
public int Ynt { get; set; }
public NoDefaultConstructorWithBinary(System.Data.Linq.Binary val)
{
Value = val;
}
}
[Fact]
public void TestNoDefaultConstructorBinary()
{
byte[] orig = new byte[20];
new Random(123456).NextBytes(orig);
var input = new System.Data.Linq.Binary(orig);
var output = connection.Query<NoDefaultConstructorWithBinary>("select @input as val", new { input }).First().Value;
output.ToArray().IsSequenceEqualTo(orig);
}
#endif
public class AbstractInheritance
{
public abstract class Order
{
internal int Internal { get; set; }
protected int Protected { get; set; }
public int Public { get; set; }
public int ProtectedVal => Protected;
}
public class ConcreteOrder : Order
{
public int Concrete { get; set; }
}
}
class MultipleConstructors
{
public MultipleConstructors()
{
}
public MultipleConstructors(int a, string b)
{
A = a + 1;
B = b + "!";
}
public int A { get; set; }
public string B { get; set; }
}
class ConstructorsWithAccessModifiers
{
private ConstructorsWithAccessModifiers()
{
}
public ConstructorsWithAccessModifiers(int a, string b)
{
A = a + 1;
B = b + "!";
}
public int A { get; set; }
public string B { get; set; }
}
class NoDefaultConstructor
{
public NoDefaultConstructor(int a1, int? b1, float f1, string s1, Guid G1)
{
A = a1;
B = b1;
F = f1;
S = s1;
G = G1;
}
public int A { get; set; }
public int? B { get; set; }
public float F { get; set; }
public string S { get; set; }
public Guid G { get; set; }
}
class NoDefaultConstructorWithChar
{
public NoDefaultConstructorWithChar(char c1, char? c2, char? c3)
{
Char1 = c1;
Char2 = c2;
Char3 = c3;
}
public char Char1 { get; set; }
public char? Char2 { get; set; }
public char? Char3 { get; set; }
}
class NoDefaultConstructorWithEnum
{
public NoDefaultConstructorWithEnum(ShortEnum e1, ShortEnum? n1, ShortEnum? n2)
{
E = e1;
NE1 = n1;
NE2 = n2;
}
public ShortEnum E { get; set; }
public ShortEnum? NE1 { get; set; }
public ShortEnum? NE2 { get; set; }
}
}
}
using Dapper;
using System;
using System.Data;
using System.Linq;
using Xunit;
#if DOTNET5_2
using IDbCommand = System.Data.Common.DbCommand;
using IDbDataParameter = System.Data.Common.DbParameter;
using IDbConnection = System.Data.Common.DbConnection;
using IDbTransaction = System.Data.Common.DbTransaction;
using IDataReader = System.Data.Common.DbDataReader;
#endif
namespace SqlMapper
{
public partial class Tests
{
[Fact]
public void TestEnumWeirdness()
{
connection.Query<TestEnumClass>("select null as [EnumEnum]").First().EnumEnum.IsEqualTo(null);
connection.Query<TestEnumClass>("select cast(1 as tinyint) as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
}
[Fact]
public void TestEnumStrings()
{
connection.Query<TestEnumClassNoNull>("select 'BLA' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
connection.Query<TestEnumClassNoNull>("select 'bla' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
connection.Query<TestEnumClass>("select 'BLA' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
connection.Query<TestEnumClass>("select 'bla' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
}
[Fact]
public void TestEnumParamsWithNullable()
{
EnumParam a = EnumParam.A;
EnumParam? b = EnumParam.B, c = null;
var obj = connection.Query<EnumParamObject>("select @a as A, @b as B, @c as C",
new { a, b, c }).Single();
obj.A.IsEqualTo(EnumParam.A);
obj.B.IsEqualTo(EnumParam.B);
obj.C.IsEqualTo(null);
}
[Fact]
public void TestEnumParamsWithoutNullable()
{
EnumParam a = EnumParam.A;
EnumParam b = EnumParam.B, c = 0;
var obj = connection.Query<EnumParamObjectNonNullable>("select @a as A, @b as B, @c as C",
new { a, b, c }).Single();
obj.A.IsEqualTo(EnumParam.A);
obj.B.IsEqualTo(EnumParam.B);
obj.C.IsEqualTo((EnumParam)0);
}
enum EnumParam : short
{
None, A, B
}
class EnumParamObject
{
public EnumParam A { get; set; }
public EnumParam? B { get; set; }
public EnumParam? C { get; set; }
}
class EnumParamObjectNonNullable
{
public EnumParam A { get; set; }
public EnumParam? B { get; set; }
public EnumParam? C { get; set; }
}
enum TestEnum : byte
{
Bla = 1
}
class TestEnumClass
{
public TestEnum? EnumEnum { get; set; }
}
class TestEnumClassNoNull
{
public TestEnum EnumEnum { get; set; }
}
}
}
This diff is collapsed.
This diff is collapsed.
using Dapper;
using System;
using System.Data;
using System.Linq;
using Xunit;
#if DOTNET5_2
using IDbCommand = System.Data.Common.DbCommand;
using IDbDataParameter = System.Data.Common.DbParameter;
using IDbConnection = System.Data.Common.DbConnection;
using IDbTransaction = System.Data.Common.DbTransaction;
using IDataReader = System.Data.Common.DbDataReader;
#endif
namespace SqlMapper
{
public partial class Tests
{
[Fact]
public void TestQueryMultipleBuffered()
{
using (var grid = connection.QueryMultiple("select 1; select 2; select @x; select 4", new { x = 3 }))
{
var a = grid.Read<int>();
var b = grid.Read<int>();
var c = grid.Read<int>();
var d = grid.Read<int>();
a.Single().Equals(1);
b.Single().Equals(2);
c.Single().Equals(3);
d.Single().Equals(4);
}
}
[Fact]
public void TestQueryMultipleNonBufferedIncorrectOrder()
{
using (var grid = connection.QueryMultiple("select 1; select 2; select @x; select 4", new { x = 3 }))
{
var a = grid.Read<int>(false);
try
{
var b = grid.Read<int>(false);
throw new InvalidOperationException(); // should have thrown
}
catch (InvalidOperationException)
{
// that's expected
}
}
}
[Fact]
public void TestQueryMultipleNonBufferedCorrectOrder()
{
using (var grid = connection.QueryMultiple("select 1; select 2; select @x; select 4", new { x = 3 }))
{
var a = grid.Read<int>(false).Single();
var b = grid.Read<int>(false).Single();
var c = grid.Read<int>(false).Single();
var d = grid.Read<int>(false).Single();
a.Equals(1);
b.Equals(2);
c.Equals(3);
d.Equals(4);
}
}
[Fact]
public void TestMultiReaderBasic()
{
var sql = @"select 1 as Id union all select 2 as Id select 'abc' as name select 1 as Id union all select 2 as Id";
int i, j;
string s;
using (var multi = connection.QueryMultiple(sql))
{
i = multi.Read<int>().First();
s = multi.Read<string>().Single();
j = multi.Read<int>().Sum();
}
Assert.IsEqualTo(i, 1);
Assert.IsEqualTo(s, "abc");
Assert.IsEqualTo(j, 3);
}
[Fact]
public void TestReadDynamicWithGridReader()
{
var createSql = @"
create table #Users (Id int, Name varchar(20))
create table #Posts (Id int, OwnerId int, Content varchar(20))
insert #Users values(99, 'Sam')
insert #Users values(2, 'I am')
insert #Posts values(1, 99, 'Sams Post1')
insert #Posts values(2, 99, 'Sams Post2')
insert #Posts values(3, null, 'no ones post')";
try
{
connection.Execute(createSql);
var sql = @"SELECT * FROM #Users ORDER BY Id
SELECT * FROM #Posts ORDER BY Id DESC";
var grid = connection.QueryMultiple(sql);
var users = grid.Read().ToList();
var posts = grid.Read().ToList();
users.Count.IsEqualTo(2);
posts.Count.IsEqualTo(3);
((int)users.First().Id).IsEqualTo(2);
((int)posts.First().Id).IsEqualTo(3);
}
finally
{
connection.Execute("drop table #Users drop table #Posts");
}
}
[Fact]
public void Issue268_ReturnQueryMultiple()
{
connection.Execute(@"create proc #TestProc268 (@a int, @b int, @c int)as
begin
select @a;
select @b
return @c;
end");
var p = new DynamicParameters(new { a = 1, b = 2, c = 3 });
p.Add("RetVal", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
using (var reader = connection.QueryMultiple("#TestProc268", p, commandType: CommandType.StoredProcedure))
{
reader.Read();
}
var retVal = p.Get<int>("RetVal");
retVal.IsEqualTo(3);
}
}
}
This diff is collapsed.
...@@ -11,11 +11,10 @@ ...@@ -11,11 +11,10 @@
"target": "project" "target": "project"
} }
}, },
"commands": { "commands": {
"Dapper.DNX.Tests": "Dapper.DNX.Tests" "Dapper.DNX.Tests": "Dapper.DNX.Tests",
"test": "xunit.runner.dnx"
}, },
"frameworks": { "frameworks": {
"net45": { "net45": {
"compilationOptions": { "compilationOptions": {
...@@ -24,13 +23,20 @@ ...@@ -24,13 +23,20 @@
}, },
"frameworkAssemblies": { "frameworkAssemblies": {
"System.Data": "4.0.0.0", "System.Data": "4.0.0.0",
"System.Runtime": "4.0.0.0",
"System.Xml": "4.0.0.0" "System.Xml": "4.0.0.0"
},
"dependencies": {
"xunit": "2.1.0"
} }
}, },
"net40": { "net40": {
"frameworkAssemblies": { "frameworkAssemblies": {
"System.Data": "4.0.0.0", "System.Data": "4.0.0.0",
"System.Xml": "4.0.0.0" "System.Xml": "4.0.0.0"
},
"dependencies": {
"xunit": "1.9.2"
} }
}, },
"dotnet5.2": { "dotnet5.2": {
...@@ -44,7 +50,23 @@ ...@@ -44,7 +50,23 @@
"System.Console": "4.0.0-beta-23409", "System.Console": "4.0.0-beta-23409",
"System.Data.SqlClient": "4.0.0-beta-23225", "System.Data.SqlClient": "4.0.0-beta-23225",
"System.Linq": "4.0.1-beta-23225", "System.Linq": "4.0.1-beta-23225",
"System.Threading": "4.0.11-beta-23225" "System.Threading": "4.0.11-beta-23225",
"xunit": "2.1.0"
}
},
"dnx451": {
"dependencies": {
"xunit": "2.1.0",
"xunit.runner.dnx": "2.1.0-rc1-build204"
}
},
"dnxcore50": {
"compilationOptions": {
"define": [ "DOTNET5_2", "ASYNC" ]
},
"dependencies": {
"xunit": "2.1.0",
"xunit.runner.dnx": "2.1.0-rc1-build204"
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment