Adding TestDbResultSet for Better Mocking (#231)

* Replacing the awful and inflexible Dictionary<string, string>[][] with a much better test data set class

* Applying all changes

* Removing unused RequestParamTests
This commit is contained in:
Benjamin Russell
2017-02-15 13:02:22 -08:00
committed by GitHub
parent d1076af43b
commit 08521cf61c
12 changed files with 265 additions and 228 deletions

View File

@@ -16,100 +16,116 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Utility
#region Test Specific Implementations
private Dictionary<string, string>[][] Data { get; set; }
private IEnumerable<TestResultSet> Data { get; }
public IEnumerator<Dictionary<string, string>[]> ResultSet { get; private set; }
public IEnumerator<TestResultSet> ResultSetEnumerator { get; }
private IEnumerator<Dictionary<string, string>> Rows { get; set; }
private IEnumerator<object[]> RowEnumerator { get; set; }
public TestDbDataReader(Dictionary<string, string>[][] data)
public TestDbDataReader(IEnumerable<TestResultSet> data)
{
Data = data;
if (Data != null)
{
ResultSet = ((IEnumerable<Dictionary<string, string>[]>) Data).GetEnumerator();
ResultSet.MoveNext();
ResultSetEnumerator = Data.GetEnumerator();
ResultSetEnumerator.MoveNext();
}
}
#endregion
public override bool HasRows
{
get { return ResultSet != null && ResultSet.Current.Length > 0; }
}
#region Properties
public override int FieldCount => ResultSetEnumerator?.Current.Columns.Count ?? 0;
public override bool HasRows => ResultSetEnumerator?.Current.Rows.Count > 0;
/// <summary>
/// Mimicks the behavior of SqlDbDataReader
/// </summary>
public override int RecordsAffected => RowEnumerator != null ? -1 : 1;
public override object this[int ordinal] => RowEnumerator.Current[ordinal];
#endregion
#region Implemented Methods
/// <summary>
/// If the row enumerator hasn't been initialized for the current result set, the
/// enumerator for the current result set is defined. Increments the enumerator
/// </summary>
/// <returns>True if tere were more rows, false otherwise</returns>
public override bool Read()
{
if (Rows == null)
if (RowEnumerator == null)
{
Rows = ((IEnumerable<Dictionary<string, string>>) ResultSet.Current).GetEnumerator();
RowEnumerator = ResultSetEnumerator.Current.GetEnumerator();
}
return Rows.MoveNext();
return RowEnumerator.MoveNext();
}
/// <summary>
/// Increments the result set enumerator and initializes the row enumerator
/// </summary>
/// <returns></returns>
public override bool NextResult()
{
if (Data == null || !ResultSet.MoveNext())
if (Data == null || !ResultSetEnumerator.MoveNext())
{
return false;
}
Rows = ((IEnumerable<Dictionary<string, string>>)ResultSet.Current).GetEnumerator();
RowEnumerator = ResultSetEnumerator.Current.GetEnumerator();
return true;
}
/// <summary>
/// Retrieves the value for the cell of the current row in the given column
/// </summary>
/// <param name="ordinal">Ordinal of the column</param>
/// <returns>The object in the cell</returns>
public override object GetValue(int ordinal)
{
return this[ordinal];
}
/// <summary>
/// Stores the values of all cells in this row in the given object array
/// </summary>
/// <param name="values">Destination for all cell values</param>
/// <returns>Number of cells in the current row</returns>
public override int GetValues(object[] values)
{
for(int i = 0; i < Rows.Current.Count; i++)
for (int i = 0; i < RowEnumerator.Current.Count(); i++)
{
values[i] = this[i];
}
return Rows.Current.Count;
}
public override object this[string name]
{
get { return Rows.Current[name]; }
}
public override object this[int ordinal]
{
get { return Rows.Current[Rows.Current.Keys.AsEnumerable().ToArray()[ordinal]]; }
}
public ReadOnlyCollection<DbColumn> GetColumnSchema()
{
if (ResultSet?.Current == null || ResultSet.Current.Length <= 0)
{
return new ReadOnlyCollection<DbColumn>(new List<DbColumn>());
}
List<DbColumn> columns = new List<DbColumn>();
for (int i = 0; i < ResultSet.Current[0].Count; i++)
{
columns.Add(new TestDbColumn(ResultSet.Current[0].Keys.ToArray()[i]));
}
return new ReadOnlyCollection<DbColumn>(columns);
return RowEnumerator.Current.Count();
}
/// <summary>
/// Whether or not a given cell in the current row is null
/// </summary>
/// <param name="ordinal">Ordinal of the column</param>
/// <returns>True if the cell is null, false otherwise</returns>
public override bool IsDBNull(int ordinal)
{
return this[ordinal] == null;
}
public override int FieldCount { get { return Rows?.Current.Count ?? 0; } }
public override int RecordsAffected
/// <returns>Collection of test columns in the current result set</returns>
public ReadOnlyCollection<DbColumn> GetColumnSchema()
{
// Mimics the behavior of SqlDataReader
get { return Rows != null ? -1 : 1; }
if (ResultSetEnumerator?.Current == null || ResultSetEnumerator.Current.Rows.Count <= 0)
{
return new ReadOnlyCollection<DbColumn>(new List<DbColumn>());
}
return new ReadOnlyCollection<DbColumn>(ResultSetEnumerator.Current.Columns);
}
#endregion
#region Not Implemented
public override bool GetBoolean(int ordinal)
@@ -207,8 +223,17 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Utility
throw new NotImplementedException();
}
public override int Depth { get; }
public override bool IsClosed { get; }
public override object this[string name]
{
get
{
throw new NotImplementedException();
}
}
public override int Depth { get { throw new NotImplementedException(); } }
public override bool IsClosed { get { throw new NotImplementedException(); } }
#endregion
}

View File

@@ -0,0 +1,49 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
namespace Microsoft.SqlTools.ServiceLayer.Test.Utility
{
public class TestResultSet : IEnumerable<object[]>
{
public List<DbColumn> Columns;
public List<object[]> Rows;
public TestResultSet(int columns, int rows)
{
Columns = Enumerable.Range(0, columns).Select(i => new TestDbColumn($"Col{i}")).Cast<DbColumn>().ToList();
Rows = new List<object[]>(rows);
for (int i = 0; i < rows; i++)
{
var row = Enumerable.Range(0, columns).Select(j => $"Cell{i}.{j}").Cast<object>().ToArray();
Rows.Add(row);
}
}
public TestResultSet(IEnumerable<DbColumn> columns, IEnumerable<object[]> rows)
{
Columns = new List<DbColumn>(columns);
Rows = new List<object[]>(rows);
}
#region IEnumerable<object[]> Impementation
public IEnumerator<object[]> GetEnumerator()
{
return (IEnumerator<object[]>) Rows.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
}

View File

@@ -4,7 +4,6 @@
//
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
@@ -199,12 +198,12 @@ namespace Microsoft.SqlTools.Test.Utility
/// </summary>
public class TestSqlCommand : DbCommand
{
internal TestSqlCommand(Dictionary<string, string>[][] data)
internal TestSqlCommand(TestResultSet[] data)
{
Data = data;
}
internal Dictionary<string, string>[][] Data { get; set; }
internal TestResultSet[] Data { get; set; }
public override void Cancel()
{
@@ -251,12 +250,12 @@ namespace Microsoft.SqlTools.Test.Utility
/// </summary>
public class TestSqlConnection : DbConnection
{
internal TestSqlConnection(Dictionary<string, string>[][] data)
internal TestSqlConnection(TestResultSet[] data)
{
Data = data;
}
internal Dictionary<string, string>[][] Data { get; set; }
internal TestResultSet[] Data { get; set; }
protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel)
{