232 lines
8.8 KiB
C#
232 lines
8.8 KiB
C#
using Knoks.Framework.DataAccess;
|
||
using Microsoft.Extensions.Logging;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Data.SqlClient;
|
||
using System.Linq;
|
||
using System.Text.RegularExpressions;
|
||
using System.Threading.Tasks;
|
||
using Xunit;
|
||
|
||
namespace Knoks.Test.Integrations.Framework
|
||
{
|
||
public class ProcExecutorTests : IDisposable
|
||
{
|
||
#region Static SQL Commantd
|
||
|
||
private const string TableName = "Test_Table_Executor";
|
||
private const string GetProcName = "Test_Proc_Get_Executor";
|
||
private const string SetProcName = "Test_Proc_Set_Executor";
|
||
|
||
private static string[] SqlCommands = new[] {
|
||
@"IF EXISTS (SELECT * FROM SYSOBJECTS WHERE NAME = 'Test_Proc_Get_Executor' AND TYPE = 'P')
|
||
DROP PROCEDURE [Test_Proc_Get_Executor];",
|
||
//-------------------------------------------------------------------------------------
|
||
@"IF EXISTS (SELECT * FROM SYSOBJECTS WHERE NAME = 'Test_Proc_Set_Executor' AND TYPE = 'P')
|
||
DROP PROCEDURE [Test_Proc_Set_Executor];",
|
||
//-------------------------------------------------------------------------------------
|
||
@"IF EXISTS (SELECT * FROM SYSOBJECTS WHERE NAME='Test_Table_Executor' AND XTYPE = 'U')
|
||
DROP TABLE [Test_Table_Executor];",
|
||
//-------------------------------------------------------------------------------------
|
||
@"CREATE TABLE [Test_Table_Executor]
|
||
(
|
||
Id BIGINT NOT NULL IDENTITY(1,1),
|
||
Col1 BIGINT NOT NULL,
|
||
Col2 VARCHAR(50) NOT NULL,
|
||
Col3 NVARCHAR(50) NOT NULL,
|
||
Col4 DateTime2 NOT NULL
|
||
);",
|
||
//-------------------------------------------------------------------------------------
|
||
@"CREATE PROCEDURE [Test_Proc_Get_Executor]
|
||
@Id BIGINT = NULL
|
||
AS
|
||
SELECT * FROM [Test_Table_Executor] WHERE [Id] = ISNULL(@Id, [Id]);
|
||
|
||
RETURN 0",
|
||
//-------------------------------------------------------------------------------------
|
||
@"CREATE PROCEDURE [Test_Proc_Set_Executor]
|
||
@Col1 BIGINT,
|
||
@Col2 VARCHAR(50),
|
||
@Col3 NVARCHAR(50),
|
||
@Col4 DateTime2,
|
||
@Id BIGINT OUT
|
||
AS
|
||
INSERT INTO [Test_Table_Executor] VALUES (@Col1, @Col2, @Col3, @Col4);
|
||
|
||
SET @Id = SCOPE_IDENTITY()
|
||
|
||
RETURN 0"
|
||
};
|
||
|
||
static ProcExecutorTests()
|
||
{
|
||
for (var i = 0; i < SqlCommands.Length; i++)
|
||
{
|
||
SqlCommands[i] = Regex.Replace(SqlCommands[i], "Test_Table_Executor", TableName);
|
||
SqlCommands[i] = Regex.Replace(SqlCommands[i], "Test_Proc_Get_Executor", GetProcName);
|
||
SqlCommands[i] = Regex.Replace(SqlCommands[i], "Test_Proc_Set_Executor", SetProcName);
|
||
}
|
||
}
|
||
|
||
private static void SqlRunner(IEnumerable<string> sqls)
|
||
{
|
||
using (var con = new SqlConnection(Config.DefaultDbConnection))
|
||
{
|
||
con.Open();
|
||
foreach (var sql in sqls)
|
||
{
|
||
using (var cmd = new SqlCommand(string.Format(sql), con))
|
||
{
|
||
cmd.ExecuteNonQuery();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private static void InitializeDatabaseEntities()
|
||
{
|
||
SqlRunner(SqlCommands);
|
||
}
|
||
|
||
private static void DestroyDatabaseEntities()
|
||
{
|
||
SqlRunner(SqlCommands.Take(3));
|
||
}
|
||
|
||
#endregion
|
||
|
||
private ProcExecutor _executor;
|
||
|
||
public ProcExecutorTests()
|
||
{
|
||
SqlRunner(SqlCommands);
|
||
_executor = new ProcExecutor(Config.DbConnections, new Logger<ProcExecutor>(new LoggerFactory()));
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
SqlRunner(SqlCommands.Take(2));
|
||
}
|
||
|
||
private class TestRecord
|
||
{
|
||
public long Col1 { get; set; }
|
||
public string Col2 { get; set; }
|
||
public string Col3 { get; set; }
|
||
public DateTime Col4 { get; set; }
|
||
|
||
[ProcParamIgnore]
|
||
public string Col5 { get; set; } = "NotExistColumnInDb";
|
||
}
|
||
|
||
class TestRecordComparer : IEqualityComparer<TestRecord>
|
||
{
|
||
public static readonly TestRecordComparer Instance = new TestRecordComparer();
|
||
|
||
public bool Equals(TestRecord x, TestRecord y)
|
||
{
|
||
return
|
||
x.Col1 == y.Col1 &&
|
||
x.Col2 == y.Col2 &&
|
||
x.Col3 == y.Col3 &&
|
||
x.Col4 == y.Col4;
|
||
}
|
||
|
||
public int GetHashCode(TestRecord obj)
|
||
{
|
||
return obj.GetHashCode();
|
||
}
|
||
}
|
||
|
||
[Fact(DisplayName = "GeneralPassingTest")]
|
||
public async Task GeneralPassingTest()
|
||
{
|
||
var rowsExpected = new List<TestRecord>
|
||
{
|
||
new TestRecord { Col1 = 1, Col2 = "Text 2-1", Col3 = "Text 3-1", Col4 = DateTime.UtcNow },
|
||
new TestRecord { Col1 = 2, Col2 = "Text 2-2", Col3 = "Text 3-2", Col4 = DateTime.UtcNow },
|
||
new TestRecord { Col1 = 3, Col2 = "Text 2-3", Col3 = "Text 3-3", Col4 = DateTime.UtcNow },
|
||
new TestRecord { Col1 = 4, Col2 = "Text 2-4", Col3 = "Text 3-4", Col4 = DateTime.UtcNow },
|
||
new TestRecord { Col1 = 5, Col2 = "Text 2-5", Col3 = "Text 3-5", Col4 = DateTime.UtcNow }
|
||
};
|
||
|
||
var rowsActual = new List<TestRecord>();
|
||
|
||
foreach (var rowExpected in rowsExpected)
|
||
{
|
||
var dr = await _executor.Go(SetProcName, rowExpected);
|
||
rowsActual.Add((await _executor.Go(GetProcName, dr.OutputParams.First())).Тables[0][0].To<TestRecord>());
|
||
};
|
||
|
||
Assert.Equal(rowsExpected, rowsActual, TestRecordComparer.Instance);
|
||
}
|
||
|
||
[Fact(DisplayName = "ParamPassingTest")]
|
||
public async Task ParamsPassingTest()
|
||
{
|
||
var testRow = new TestRecord { Col1 = 1, Col2 = "Text 1", Col3 = "Text 1", Col4 = DateTime.UtcNow };
|
||
var rowsExpected = new List<TestRecord> { testRow, testRow, testRow, testRow };
|
||
|
||
var d = new Dictionary<string, object> { { "Col1", testRow.Col1 }, { "Col2", testRow.Col2 }, { "Col3", testRow.Col3 }, { "Col4", testRow.Col4 } };
|
||
var objects = new List<object> { testRow, d, d.ToArray(), d.ToList() };
|
||
|
||
var rowsActual = new List<TestRecord>();
|
||
|
||
foreach (var obj in objects)
|
||
{
|
||
var dr = await _executor.Go(SetProcName, obj);
|
||
rowsActual.Add((await _executor.Go(GetProcName, dr.OutputParams.First())).Тables[0][0].To<TestRecord>());
|
||
}
|
||
|
||
Assert.Equal(rowsExpected, rowsActual, TestRecordComparer.Instance);
|
||
}
|
||
|
||
[Fact(DisplayName = "MultiParamsPassingTest")]
|
||
public async Task MultiParamsPassingTest()
|
||
{
|
||
var rowsExpected = new TestRecord { Col1 = 1, Col2 = "Text 1", Col3 = "Text 1", Col4 = DateTime.UtcNow };
|
||
|
||
var dr = await _executor.Go(SetProcName, new { Col1 = rowsExpected.Col1, Col2 = rowsExpected.Col2 }, new { Col3 = rowsExpected.Col3, Col4 = rowsExpected.Col4 });
|
||
var rowsActual = (await _executor.Go(GetProcName, dr.OutputParams.First())).Тables[0][0].To<TestRecord>();
|
||
|
||
Assert.Equal(rowsExpected, rowsActual, TestRecordComparer.Instance);
|
||
}
|
||
|
||
[ProcParamIgnore]
|
||
private class IgnoreTestRecord
|
||
{
|
||
public long Col1 { get; set; }
|
||
public string Col2 { get; set; }
|
||
public string Col3 { get; set; }
|
||
public DateTime Col4 { get; set; }
|
||
}
|
||
|
||
[Fact(DisplayName = "Ignore record class")]
|
||
public async Task IgnoreRecordClass()
|
||
{
|
||
await Assert.ThrowsAsync<ArgumentException>(async () =>
|
||
{
|
||
await _executor.Go(SetProcName, new IgnoreTestRecord());
|
||
});
|
||
}
|
||
|
||
[Fact(DisplayName = "Ignore record KeyValuePair")]
|
||
public async Task IgnoreRecordKeyValuePair()
|
||
{
|
||
await Assert.ThrowsAsync<SqlException>(async () =>
|
||
{
|
||
await _executor.Go(SetProcName, new KeyValuePair<string, object>("key", new IgnoreTestRecord()));
|
||
});
|
||
}
|
||
|
||
[Fact(DisplayName = "Ignore records in Dictionary")]
|
||
public async Task IgnoreRecordDictionary()
|
||
{
|
||
await Assert.ThrowsAsync<SqlException>(async () =>
|
||
{
|
||
await _executor.Go(SetProcName, new Dictionary<string, object> { { "k1", new IgnoreTestRecord() }, { "k2", new IgnoreTestRecord() } });
|
||
});
|
||
}
|
||
}
|
||
}
|