From 25f2f4766e41c28542ec07666e71cdcaae03936c Mon Sep 17 00:00:00 2001 From: Alexander <2088777+ajeckmans@users.noreply.github.com> Date: Mon, 4 Mar 2024 16:41:29 +0100 Subject: [PATCH] Preliminary work on adding a table helpers class that can be resolved from the DI. This enables per-scenario differing value retrievers. --- .../InstanceComparisonExtensionMethods.cs | 1 + .../Wrappers/SetComparisonExtensionMethods.cs | 2 +- .../Wrappers/TableExtensionMethods.cs | 24 +- .../ProjectTests.cs | 2 +- Reqnroll/Assist/EnumerableProjection.cs | 4 +- Reqnroll/Assist/FindInSetExtensionMethods.cs | 18 +- .../InstanceComparisonExtensionMethods.cs | 67 ++- Reqnroll/Assist/ProjectionExtensionMethods.cs | 13 +- .../ReqnrollDefaultValueRetrieverList.cs | 6 +- Reqnroll/Assist/Service.cs | 4 +- Reqnroll/Assist/SetComparer.cs | 46 +- .../Assist/SetComparisonExtensionMethods.cs | 6 +- Reqnroll/Assist/TEHelpers.cs | 85 ++-- Reqnroll/Assist/TableExtensionMethods.cs | 9 +- Reqnroll/Assist/TableHelpers.cs | 214 +++++++++ .../ValueRetrievers/ArrayValueRetriever.cs | 7 +- .../EnumerableValueRetriever.cs | 10 +- .../ValueRetrievers/ListValueRetriever.cs | 4 + .../CreateInstanceHelperMethodTests.cs | 1 + .../FindAllInSetExtensionMethodsTests.cs | 1 + .../FindInSetExtensionMethodTests.cs | 1 + ...InstanceComparisonExtensionMethodsTests.cs | 2 +- ...InstanceEquivalenceExtensionMethodTests.cs | 1 + .../AssistTests/ProjectionTests.cs | 2 +- .../AssistTests/RowExtensionMethodTests.cs | 1 + ...ComparisonExtensionMethods_MessageTests.cs | 122 +++-- ...etComparisonExtensionMethods_ThrowTests.cs | 3 + ...lablesWithCustomNullValueRetrieverTests.cs | 13 +- .../SituationalTests/NullableEnumTests.cs | 20 +- .../CreateInstanceHelperMethodTestBase.cs | 3 +- .../CreateInstanceHelperMethodTests.cs | 2 + ...tanceHelperMethodTests_WithArrayOfEnums.cs | 2 + ...anceHelperMethodTests_WithArrayOfValues.cs | 2 + ...reateInstanceHelperMethodTests_WithFunc.cs | 2 + ...stanceHelperMethodTests_WithListOfEnums.cs | 2 + ...tanceHelperMethodTests_WithListOfValues.cs | 2 + .../CreateInstanceHelperStandardTypesTests.cs | 1 + .../CreateSetHelperMethodTests.cs | 1 + .../CreateSetHelperMethodTests_WithFunc.cs | 2 + ...MethodTests_WithFuncAndTableRowArgument.cs | 1 + .../CreateSetWithNullableValuesTests.cs | 1 + .../FillInstanceHelperMethodTests.cs | 2 + .../TableHelpersTests/CompatibilityTests.cs | 36 ++ .../CreateInstanceHelperMethodTestBase.cs | 151 +++++++ .../CreateInstanceHelperMethodTests.cs | 119 +++++ .../CreateSetHelperMethodTests.cs | 422 ++++++++++++++++++ .../ArrayRetrieverTests.cs | 7 +- .../EnumerableRetrieverTests.cs | 9 +- .../ValueRetrieverTests/ListRetrieverTests.cs | 5 +- ...mpleOfValueRetrieverAndComparerAddition.cs | 30 +- .../StepDefinitions/ExecutionResultSteps.cs | 10 +- .../StepDefinitions/GherkinParserSteps.cs | 8 +- 52 files changed, 1273 insertions(+), 236 deletions(-) create mode 100644 Reqnroll/Assist/TableHelpers.cs create mode 100644 Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CompatibilityTests.cs create mode 100644 Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CreateInstanceHelperMethodTestBase.cs create mode 100644 Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CreateInstanceHelperMethodTests.cs create mode 100644 Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CreateSetHelperMethodTests.cs diff --git a/Plugins/Reqnroll.SpecFlowCompatibility.ReqnrollPlugin/Wrappers/InstanceComparisonExtensionMethods.cs b/Plugins/Reqnroll.SpecFlowCompatibility.ReqnrollPlugin/Wrappers/InstanceComparisonExtensionMethods.cs index b38a6ee0c..f74868cad 100644 --- a/Plugins/Reqnroll.SpecFlowCompatibility.ReqnrollPlugin/Wrappers/InstanceComparisonExtensionMethods.cs +++ b/Plugins/Reqnroll.SpecFlowCompatibility.ReqnrollPlugin/Wrappers/InstanceComparisonExtensionMethods.cs @@ -16,6 +16,7 @@ public static void CompareToInstance(this Table table, T instance) /// Indicates whether the table is equivalent to the specified instance by comparing the values of all /// columns against the properties of the instance. Will return false after finding the first difference. /// + [Obsolete("Use TableHelpers instead")] public static bool IsEquivalentToInstance(this Table table, T instance) { return Reqnroll.InstanceComparisonExtensionMethods.IsEquivalentToInstance(table, instance); diff --git a/Plugins/Reqnroll.SpecFlowCompatibility.ReqnrollPlugin/Wrappers/SetComparisonExtensionMethods.cs b/Plugins/Reqnroll.SpecFlowCompatibility.ReqnrollPlugin/Wrappers/SetComparisonExtensionMethods.cs index f1a85efc0..752443be7 100644 --- a/Plugins/Reqnroll.SpecFlowCompatibility.ReqnrollPlugin/Wrappers/SetComparisonExtensionMethods.cs +++ b/Plugins/Reqnroll.SpecFlowCompatibility.ReqnrollPlugin/Wrappers/SetComparisonExtensionMethods.cs @@ -1,5 +1,5 @@ +using System; using System.Collections.Generic; -using Reqnroll; // ReSharper disable once CheckNamespace namespace TechTalk.SpecFlow.Assist; diff --git a/Plugins/Reqnroll.SpecFlowCompatibility.ReqnrollPlugin/Wrappers/TableExtensionMethods.cs b/Plugins/Reqnroll.SpecFlowCompatibility.ReqnrollPlugin/Wrappers/TableExtensionMethods.cs index 96e79ec3c..3611403c3 100644 --- a/Plugins/Reqnroll.SpecFlowCompatibility.ReqnrollPlugin/Wrappers/TableExtensionMethods.cs +++ b/Plugins/Reqnroll.SpecFlowCompatibility.ReqnrollPlugin/Wrappers/TableExtensionMethods.cs @@ -10,61 +10,61 @@ public static class TableHelperExtensionMethods { public static T CreateInstance(this Table table) { - return Reqnroll.TableHelperExtensionMethods.CreateInstance(table); + return Reqnroll.TableExtensionMethods.CreateInstance(table); } public static T CreateInstance(this Table table, InstanceCreationOptions creationOptions) { - return Reqnroll.TableHelperExtensionMethods.CreateInstance(table, creationOptions); + return Reqnroll.TableExtensionMethods.CreateInstance(table, creationOptions); } public static T CreateInstance(this Table table, Func methodToCreateTheInstance) { - return Reqnroll.TableHelperExtensionMethods.CreateInstance(table, methodToCreateTheInstance); + return Reqnroll.TableExtensionMethods.CreateInstance(table, methodToCreateTheInstance); } public static T CreateInstance(this Table table, Func methodToCreateTheInstance, InstanceCreationOptions creationOptions) { - return Reqnroll.TableHelperExtensionMethods.CreateInstance(table, methodToCreateTheInstance, creationOptions); + return Reqnroll.TableExtensionMethods.CreateInstance(table, methodToCreateTheInstance, creationOptions); } public static void FillInstance(this Table table, object instance) { - Reqnroll.TableHelperExtensionMethods.FillInstance(table, instance); + Reqnroll.TableExtensionMethods.FillInstance(table, instance); } public static void FillInstance(this Table table, object instance, InstanceCreationOptions creationOptions) { - Reqnroll.TableHelperExtensionMethods.FillInstance(table, instance, creationOptions); + Reqnroll.TableExtensionMethods.FillInstance(table, instance, creationOptions); } public static IEnumerable CreateSet(this Table table) { - return Reqnroll.TableHelperExtensionMethods.CreateSet(table); + return Reqnroll.TableExtensionMethods.CreateSet(table); } public static IEnumerable CreateSet(this Table table, InstanceCreationOptions creationOptions) { - return Reqnroll.TableHelperExtensionMethods.CreateSet(table, creationOptions); + return Reqnroll.TableExtensionMethods.CreateSet(table, creationOptions); } public static IEnumerable CreateSet(this Table table, Func methodToCreateEachInstance) { - return Reqnroll.TableHelperExtensionMethods.CreateSet(table, methodToCreateEachInstance); + return Reqnroll.TableExtensionMethods.CreateSet(table, methodToCreateEachInstance); } public static IEnumerable CreateSet(this Table table, Func methodToCreateEachInstance, InstanceCreationOptions creationOptions) { - return Reqnroll.TableHelperExtensionMethods.CreateSet(table, methodToCreateEachInstance, creationOptions); + return Reqnroll.TableExtensionMethods.CreateSet(table, methodToCreateEachInstance, creationOptions); } public static IEnumerable CreateSet(this Table table, Func methodToCreateEachInstance) { - return Reqnroll.TableHelperExtensionMethods.CreateSet(table, methodToCreateEachInstance); + return Reqnroll.TableExtensionMethods.CreateSet(table, methodToCreateEachInstance); } public static IEnumerable CreateSet(this Table table, Func methodToCreateEachInstance, InstanceCreationOptions creationOptions) { - return Reqnroll.TableHelperExtensionMethods.CreateSet(table, methodToCreateEachInstance, creationOptions); + return Reqnroll.TableExtensionMethods.CreateSet(table, methodToCreateEachInstance, creationOptions); } } \ No newline at end of file diff --git a/Reqnroll.TestProjectGenerator/Reqnroll.TestProjectGenerator.Tests/ProjectTests.cs b/Reqnroll.TestProjectGenerator/Reqnroll.TestProjectGenerator.Tests/ProjectTests.cs index 1797b9360..89a8b6894 100644 --- a/Reqnroll.TestProjectGenerator/Reqnroll.TestProjectGenerator.Tests/ProjectTests.cs +++ b/Reqnroll.TestProjectGenerator/Reqnroll.TestProjectGenerator.Tests/ProjectTests.cs @@ -259,7 +259,7 @@ public void CreateEmptyCSharpCore3_1ProjectInNewFormat() string projectFileContent = GetProjectFileContent(solutionFolder, project); projectFileContent.Should() - .Contain("\r\n \r\n netcoreapp3.1\r\n \r\n"); + .Contain("\r\n \r\n net6.0\r\n \r\n"); } [Fact] diff --git a/Reqnroll/Assist/EnumerableProjection.cs b/Reqnroll/Assist/EnumerableProjection.cs index 8e3d3d376..aec65d205 100644 --- a/Reqnroll/Assist/EnumerableProjection.cs +++ b/Reqnroll/Assist/EnumerableProjection.cs @@ -9,14 +9,14 @@ public class EnumerableProjection : IEnumerable> private readonly IEnumerable collection; private readonly IEnumerable properties; - public EnumerableProjection(Table table, IEnumerable collection = null) + public EnumerableProjection(TableHelpers tableHelpers, Table table, IEnumerable collection = null) { if (table == null && collection == null) throw new ArgumentNullException(nameof(table), "Either table or projectCollection must be specified"); if (table != null) properties = table.Header; - this.collection = collection ?? table.CreateSet(); + this.collection = collection ?? tableHelpers.CreateSet(table); } public IEnumerator> GetEnumerator() diff --git a/Reqnroll/Assist/FindInSetExtensionMethods.cs b/Reqnroll/Assist/FindInSetExtensionMethods.cs index 51253a336..6722122cb 100644 --- a/Reqnroll/Assist/FindInSetExtensionMethods.cs +++ b/Reqnroll/Assist/FindInSetExtensionMethods.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; @@ -7,26 +8,25 @@ public static class FindInSetExtensionMethods { public static T FindInSet(this Table table, IEnumerable set) { - var instanceTable = TEHelpers.GetTheProperInstanceTable(table, typeof (T)); + var instanceTable = TEHelpers.GetTheProperInstanceTable(table, typeof(T)); - var matches = set.Where(instance => InstanceMatchesTable(instance, instanceTable)).ToArray(); + var matches = set.Where(instance => InstanceMatchesTable(Service.Instance, instance, instanceTable)).ToArray(); - if (matches.Length > 1) - throw new ComparisonException("Multiple instances match the table"); + if (matches.Length > 1) throw new ComparisonException("Multiple instances match the table"); return matches.FirstOrDefault(); } public static IEnumerable FindAllInSet(this Table table, IEnumerable set) { - var instanceTable = TEHelpers.GetTheProperInstanceTable(table, typeof (T)); + var instanceTable = TEHelpers.GetTheProperInstanceTable(table, typeof(T)); - return set.Where(instance => InstanceMatchesTable(instance, instanceTable)).ToArray(); + return set.Where(instance => InstanceMatchesTable(Service.Instance, instance, instanceTable)).ToArray(); } - private static bool InstanceMatchesTable(T instance, Table table) + private static bool InstanceMatchesTable(Service service, T instance, Table table) { - return table.Rows.All(row => !InstanceComparisonExtensionMethods.ThereIsADifference(instance, row)); + return table.Rows.All(row => !InstanceComparisonExtensionMethods.ThereIsADifference(service, instance, row)); } } -} \ No newline at end of file +} diff --git a/Reqnroll/Assist/InstanceComparisonExtensionMethods.cs b/Reqnroll/Assist/InstanceComparisonExtensionMethods.cs index cf21c3a7e..78b818966 100644 --- a/Reqnroll/Assist/InstanceComparisonExtensionMethods.cs +++ b/Reqnroll/Assist/InstanceComparisonExtensionMethods.cs @@ -8,17 +8,15 @@ namespace Reqnroll { public static class InstanceComparisonExtensionMethods { - public static void CompareToInstance(this Table table, T instance) { AssertThatTheInstanceExists(instance); var instanceTable = TEHelpers.GetTheProperInstanceTable(table, typeof(T)); - var differences = FindAnyDifferences(instanceTable, instance); + var differences = FindAnyDifferences(Service.Instance, instanceTable, instance); - if (ThereAreAnyDifferences(differences)) - ThrowAnExceptionThatDescribesThoseDifferences(differences); + if (ThereAreAnyDifferences(differences)) ThrowAnExceptionThatDescribesThoseDifferences(differences); } /// @@ -31,13 +29,12 @@ public static bool IsEquivalentToInstance(this Table table, T instance) var instanceTable = TEHelpers.GetTheProperInstanceTable(table, typeof(T)); - return HasDifference(instanceTable, instance) == false; + return HasDifference(Service.Instance, instanceTable, instance) == false; } private static void AssertThatTheInstanceExists(T instance) { - if (instance == null) - throw new ComparisonException("The item to compare was null."); + if (instance == null) throw new ComparisonException("The item to compare was null."); } private static void ThrowAnExceptionThatDescribesThoseDifferences(IEnumerable differences) @@ -47,23 +44,25 @@ private static void ThrowAnExceptionThatDescribesThoseDifferences(IEnumerable differences) { - return differences.Aggregate(@"The following fields did not match:", - (sum, next) => sum + (Environment.NewLine + next.Description)); + return differences.Aggregate( + @"The following fields did not match:", + (sum, next) => sum + (Environment.NewLine + next.Description)); } - private static Difference[] FindAnyDifferences(Table table, T instance) + private static Difference[] FindAnyDifferences(Service service, Table table, T instance) { return (from row in table.Rows - where ThePropertyDoesNotExist(instance, row) || TheValuesDoNotMatch(instance, row) - select CreateDifferenceForThisRow(instance, row)).ToArray(); + where ThePropertyDoesNotExist(instance, row) || TheValuesDoNotMatch(service, instance, row) + select CreateDifferenceForThisRow(service, instance, row)).ToArray(); } - private static bool HasDifference(Table table, T instance) + private static bool HasDifference(Service service, Table table, T instance) { // This method exists so it will stop evaluating the instance (hence stop using Reflection) // after the first difference is found. - return (from row in table.Rows select row) - .Any(row => ThePropertyDoesNotExist(instance, row) || TheValuesDoNotMatch(instance, row)); + return (from row in table.Rows + select row) + .Any(row => ThePropertyDoesNotExist(instance, row) || TheValuesDoNotMatch(service, instance, row)); } private static bool ThereAreAnyDifferences(IEnumerable differences) @@ -73,23 +72,26 @@ private static bool ThereAreAnyDifferences(IEnumerable differences) internal static bool ThePropertyDoesNotExist(T instance, DataTableRow row) { - return instance.GetType().GetProperties() - .Any(property => TEHelpers.IsMemberMatchingToColumnName(property, row.Id())) == false; + return instance.GetType() + .GetProperties() + .Any(property => TEHelpers.IsMemberMatchingToColumnName(property, row.Id())) + == false; } - internal static bool ThereIsADifference(T instance, DataTableRow row) + internal static bool ThereIsADifference(Service service, T instance, DataTableRow row) { - return ThePropertyDoesNotExist(instance, row) || TheValuesDoNotMatch(instance, row); + return ThePropertyDoesNotExist(instance, row) || TheValuesDoNotMatch(service, instance, row); } - private static bool TheValuesDoNotMatch(T instance, DataTableRow row) + private static bool TheValuesDoNotMatch(Service service, T instance, DataTableRow row) { var expected = GetTheExpectedValue(row); var propertyValue = instance.GetPropertyValue(row.Id()); - var comparer = FindValueComparerForValue(propertyValue); + var comparer = FindValueComparerForValue(service, propertyValue); return comparer - .Compare(expected, propertyValue) == false; + .Compare(expected, propertyValue) + == false; } private static string GetTheExpectedValue(DataTableRow row) @@ -97,26 +99,23 @@ private static string GetTheExpectedValue(DataTableRow row) return row.Value(); } - private static Difference CreateDifferenceForThisRow(T instance, DataTableRow row) + private static Difference CreateDifferenceForThisRow(Service service, T instance, DataTableRow row) { var propertyName = row.Id(); - if (ThePropertyDoesNotExist(instance, row)) - return new PropertyDoesNotExist(propertyName); + if (ThePropertyDoesNotExist(instance, row)) return new PropertyDoesNotExist(propertyName); var expected = row.Value(); var actual = instance.GetPropertyValue(propertyName); - var comparer = FindValueComparerForProperty(instance, propertyName); + var comparer = FindValueComparerForProperty(service, instance, propertyName); return new PropertyDiffers(propertyName, expected, actual, comparer); } - private static IValueComparer FindValueComparerForProperty(T instance, string propertyName) => - FindValueComparerForValue( - instance.GetPropertyValue(propertyName)); + private static IValueComparer FindValueComparerForProperty(Service service, T instance, string propertyName) => + FindValueComparerForValue(service, instance.GetPropertyValue(propertyName)); - private static IValueComparer FindValueComparerForValue(object propertyValue) => - Service.Instance.ValueComparers - .FirstOrDefault(x => x.CanCompare(propertyValue)); + private static IValueComparer FindValueComparerForValue(Service service, object propertyValue) => + service.ValueComparers.FirstOrDefault(x => x.CanCompare(propertyValue)); private abstract class Difference { @@ -156,7 +155,7 @@ public PropertyDiffers(string propertyName, object expected, object actual, IVal } } - public static class TableHelpers + public static class SetComparerTableHelpers { public static string Id(this DataTableRow row) { @@ -176,4 +175,4 @@ public ComparisonException(string message) { } } -} \ No newline at end of file +} diff --git a/Reqnroll/Assist/ProjectionExtensionMethods.cs b/Reqnroll/Assist/ProjectionExtensionMethods.cs index f37b5ecb6..51410a52a 100644 --- a/Reqnroll/Assist/ProjectionExtensionMethods.cs +++ b/Reqnroll/Assist/ProjectionExtensionMethods.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; namespace Reqnroll.Assist @@ -6,22 +7,26 @@ public static class ProjectionExtensionMethods { public static IEnumerable> ToProjection(this IEnumerable collection, Table table = null) { - return new EnumerableProjection(table, collection); + var tableHelpers = new TableHelpers(Service.Instance); + return new EnumerableProjection(tableHelpers, table, collection); } public static IEnumerable> ToProjection(this Table table) { - return new EnumerableProjection(table); + var tableHelpers = new TableHelpers(Service.Instance); + return new EnumerableProjection(tableHelpers, table); } public static IEnumerable> ToProjectionOfSet(this Table table, IEnumerable collection) { - return new EnumerableProjection(table); + var tableHelpers = new TableHelpers(Service.Instance); + return new EnumerableProjection(tableHelpers, table); } public static IEnumerable> ToProjectionOfInstance(this Table table, T instance) { - return new EnumerableProjection(table); + var tableHelpers = new TableHelpers(Service.Instance); + return new EnumerableProjection(tableHelpers, table); } } } \ No newline at end of file diff --git a/Reqnroll/Assist/ReqnrollDefaultValueRetrieverList.cs b/Reqnroll/Assist/ReqnrollDefaultValueRetrieverList.cs index b73e94a81..e8c728aa9 100644 --- a/Reqnroll/Assist/ReqnrollDefaultValueRetrieverList.cs +++ b/Reqnroll/Assist/ReqnrollDefaultValueRetrieverList.cs @@ -6,7 +6,7 @@ namespace Reqnroll.Assist #nullable enable internal sealed class ReqnrollDefaultValueRetrieverList : ServiceComponentList { - public ReqnrollDefaultValueRetrieverList() + public ReqnrollDefaultValueRetrieverList(Service service) : base(new List { // Sorted by likelihood new StringValueRetriever(), @@ -19,8 +19,8 @@ public ReqnrollDefaultValueRetrieverList() new TimeSpanValueRetriever(), new GuidValueRetriever(), new EnumValueRetriever(), - new ListValueRetriever(), - new ArrayValueRetriever(), + new ListValueRetriever(service), + new ArrayValueRetriever(service), new ByteValueRetriever(), new SByteValueRetriever(), new UIntValueRetriever(), diff --git a/Reqnroll/Assist/Service.cs b/Reqnroll/Assist/Service.cs index 010f9dfdd..576fb9ca7 100644 --- a/Reqnroll/Assist/Service.cs +++ b/Reqnroll/Assist/Service.cs @@ -14,13 +14,13 @@ public class Service public Service() { ValueComparers = new ReqnrollDefaultValueComparerList(); - ValueRetrievers = new ReqnrollDefaultValueRetrieverList(); + ValueRetrievers = new ReqnrollDefaultValueRetrieverList(this); } public void RestoreDefaults() { ValueComparers = new ReqnrollDefaultValueComparerList(); - ValueRetrievers = new ReqnrollDefaultValueRetrieverList(); + ValueRetrievers = new ReqnrollDefaultValueRetrieverList(this); } [Obsolete("Use ValueComparers.Register")] diff --git a/Reqnroll/Assist/SetComparer.cs b/Reqnroll/Assist/SetComparer.cs index 1e96c76c2..ded5791f6 100644 --- a/Reqnroll/Assist/SetComparer.cs +++ b/Reqnroll/Assist/SetComparer.cs @@ -8,12 +8,14 @@ public class SetComparer { private const int MatchNotFound = -1; private readonly Table table; + private readonly TableHelpers _tableHelpers; private List> extraOrNonMatchingActualItems; private readonly ITableDiffExceptionBuilder tableDiffExceptionBuilder; - public SetComparer(Table table) + public SetComparer(Table table, TableHelpers tableHelpers) { this.table = table; + _tableHelpers = tableHelpers; tableDiffExceptionBuilder = BuildTheTableDiffExceptionBuilder(); } @@ -40,8 +42,7 @@ public void CompareToSet(IEnumerable set, bool sequentialEquality) { AssertThatAllColumnsInTheTableMatchToPropertiesOnTheType(); - if (ThereAreNoResultsAndNoExpectedResults(set)) - return; + if (ThereAreNoResultsAndNoExpectedResults(set)) return; var expectedItemsNotFoundInTheData = GetExpectedItemsNotFoundInTheData(set, sequentialEquality); @@ -64,8 +65,7 @@ private bool ThereAreNoResultsAndNoExpectedResults(IEnumerable set) private void AssertThatTheItemsMatchTheExpectedResults(IEnumerable listOfMissingItems) { - if (ExpectedItemsCouldNotBeFound(listOfMissingItems)) - ThrowAnErrorDetailingWhichItemsAreMissing(listOfMissingItems); + if (ExpectedItemsCouldNotBeFound(listOfMissingItems)) ThrowAnErrorDetailingWhichItemsAreMissing(listOfMissingItems); } private IEnumerable GetListOfExpectedItemsThatCouldNotBeFoundOrderInsensitive(IEnumerable set) @@ -103,14 +103,14 @@ private IEnumerable GetListOfExpectedItemsThatCouldNotBeFoundOrderSensitive for (var index = 0; index < Math.Min(actualItems.Count, table.Rows.Count()); index++) { var instanceTable = pivotTable.GetInstanceTable(index); - if (!ThisItemIsAMatch(instanceTable, actualItems[index])) - listOfMissingItems.Add(index + 1); + if (!ThisItemIsAMatch(instanceTable, actualItems[index])) listOfMissingItems.Add(index + 1); } extraOrNonMatchingActualItems = - listOfMissingItems.Select(index => new TableDifferenceItem(actualItems[index-1], index)).Concat( - actualItems.Skip(table.RowCount).Select(i => new TableDifferenceItem(i))) - .ToList(); + listOfMissingItems.Select(index => new TableDifferenceItem(actualItems[index - 1], index)) + .Concat( + actualItems.Skip(table.RowCount).Select(i => new TableDifferenceItem(i))) + .ToList(); var extraTableItems = table.Rows.Count() - actualItems.Count; if (extraTableItems > 0) @@ -140,24 +140,25 @@ private static void RemoveFromActualItemsSoItWillNotBeCheckedAgain(List actua actualItems.RemoveAt(matchIndex); } - private static int GetTheIndexOfTheMatchingItem(Table expectedItem, - IList actualItems) + private int GetTheIndexOfTheMatchingItem( + Table expectedItem, + IList actualItems) { for (var actualItemIndex = 0; actualItemIndex < actualItems.Count; actualItemIndex++) { var actualItem = actualItems[actualItemIndex]; - if (ThisItemIsAMatch(expectedItem, actualItem)) - return actualItemIndex; + if (ThisItemIsAMatch(expectedItem, actualItem)) return actualItemIndex; } + return MatchNotFound; } - private static bool ThisItemIsAMatch(Table expectedItem, T actualItem) + private bool ThisItemIsAMatch(Table expectedItem, T actualItem) { try { - return expectedItem.IsEquivalentToInstance(actualItem); + return _tableHelpers.IsEquivalentToInstance(expectedItem, actualItem); } catch { @@ -175,13 +176,12 @@ private void AssertThatAllColumnsInTheTableMatchToPropertiesOnTheType() var propertyInfos = typeof(T).GetProperties(); var propertiesThatDoNotExist = table.Header - .Where( - columnHeader => !propertyInfos.Any( - property => TEHelpers.IsMemberMatchingToColumnName(property, columnHeader))) - .ToList(); + .Where( + columnHeader => !propertyInfos.Any( + property => TEHelpers.IsMemberMatchingToColumnName(property, columnHeader))) + .ToList(); - if (propertiesThatDoNotExist.Any()) - throw new ComparisonException($@"The following fields do not exist:{Environment.NewLine}{string.Join(Environment.NewLine, propertiesThatDoNotExist)}"); + if (propertiesThatDoNotExist.Any()) throw new ComparisonException($@"The following fields do not exist:{Environment.NewLine}{string.Join(Environment.NewLine, propertiesThatDoNotExist)}"); } } -} \ No newline at end of file +} diff --git a/Reqnroll/Assist/SetComparisonExtensionMethods.cs b/Reqnroll/Assist/SetComparisonExtensionMethods.cs index 92d541111..7758172c3 100644 --- a/Reqnroll/Assist/SetComparisonExtensionMethods.cs +++ b/Reqnroll/Assist/SetComparisonExtensionMethods.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Reqnroll.Assist; @@ -7,8 +8,9 @@ public static class SetComparisonExtensionMethods { public static void CompareToSet(this Table table, IEnumerable set, bool sequentialEquality = false) { - var checker = new SetComparer(table); + var tableHelpers = new TableHelpers(Service.Instance); + var checker = new SetComparer(table, tableHelpers); checker.CompareToSet(set, sequentialEquality); } } -} \ No newline at end of file +} diff --git a/Reqnroll/Assist/TEHelpers.cs b/Reqnroll/Assist/TEHelpers.cs index 302b8aab5..7547222ac 100644 --- a/Reqnroll/Assist/TEHelpers.cs +++ b/Reqnroll/Assist/TEHelpers.cs @@ -13,20 +13,19 @@ internal static class TEHelpers private static readonly Regex invalidPropertyNameRegex = new Regex(InvalidPropertyNamePattern, RegexOptions.Compiled); private const string InvalidPropertyNamePattern = @"[^\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}\p{Nd}_]"; - internal static T CreateTheInstanceWithTheDefaultConstructor(Table table, InstanceCreationOptions creationOptions) + internal static T CreateTheInstanceWithTheDefaultConstructor(Service service, Table table, InstanceCreationOptions creationOptions) { var instance = (T)Activator.CreateInstance(typeof(T)); - LoadInstanceWithKeyValuePairs(table, instance, creationOptions); + LoadInstanceWithKeyValuePairs(service, table, instance, creationOptions); return instance; } - internal static T CreateTheInstanceWithTheValuesFromTheTable(Table table, InstanceCreationOptions creationOptions) + internal static T CreateTheInstanceWithTheValuesFromTheTable(Service service, Table table, InstanceCreationOptions creationOptions) { var constructor = GetConstructorMatchingToColumnNames(table); - if (constructor == null) - throw new MissingMethodException($"Unable to find a suitable constructor to create instance of {typeof(T).Name}"); + if (constructor == null) throw new MissingMethodException($"Unable to find a suitable constructor to create instance of {typeof(T).Name}"); - var membersThatNeedToBeSet = GetMembersThatNeedToBeSet(table, typeof(T)); + var membersThatNeedToBeSet = GetMembersThatNeedToBeSet(service, table, typeof(T)); var constructorParameters = constructor.GetParameters(); var parameterValues = new object[constructorParameters.Length]; @@ -42,10 +41,9 @@ where string.Equals(m.MemberName, parameterName, StringComparison.OrdinalIgnoreC if (member != null) { members.Add(member.MemberName); - parameterValues[parameterIndex] = member.GetValue(); + parameterValues[parameterIndex] = member.GetValue(service); } - else if (parameter.HasDefaultValue) - parameterValues[parameterIndex] = parameter.DefaultValue; + else if (parameter.HasDefaultValue) parameterValues[parameterIndex] = parameter.DefaultValue; } VerifyAllColumn(table, creationOptions, members); @@ -66,15 +64,17 @@ where IsMemberMatchingToColumnName(property, row.Id()) return (from constructor in typeof(T).GetConstructors() where !projectedPropertyNames.Except( - from parameter in constructor.GetParameters() - select parameter.Name, StringComparer.OrdinalIgnoreCase).Any() + from parameter in constructor.GetParameters() + select parameter.Name, + StringComparer.OrdinalIgnoreCase) + .Any() select constructor).FirstOrDefault(); } internal static bool IsMemberMatchingToColumnName(MemberInfo member, string columnName) { return member.Name.MatchesThisColumnName(columnName) - || IsMatchingAlias(member, columnName); + || IsMatchingAlias(member, columnName); } internal static bool MatchesThisColumnName(this string propertyName, string columnName) @@ -98,15 +98,15 @@ internal static string NormalizePropertyNameToMatchAgainstAColumnName(string nam return name.Replace("_", string.Empty).ToIdentifier(); } - internal static void LoadInstanceWithKeyValuePairs(Table table, object instance, InstanceCreationOptions creationOptions) + internal static void LoadInstanceWithKeyValuePairs(Service service, Table table, object instance, InstanceCreationOptions creationOptions) { - var membersThatNeedToBeSet = GetMembersThatNeedToBeSet(table, instance.GetType()); + var membersThatNeedToBeSet = GetMembersThatNeedToBeSet(service, table, instance.GetType()); var memberHandlers = membersThatNeedToBeSet.ToList(); var memberNames = memberHandlers.Select(h => h.MemberName); VerifyAllColumn(table, creationOptions, memberNames); - memberHandlers.ForEach(x => x.Setter(instance, x.GetValue())); + memberHandlers.ForEach(x => x.Setter(instance, x.GetValue(service))); } private static void VerifyAllColumn(Table table, InstanceCreationOptions creationOptions, IEnumerable memberNames) @@ -123,19 +123,19 @@ private static void VerifyAllColumn(Table table, InstanceCreationOptions creatio } } - internal static List GetMembersThatNeedToBeSet(Table table, Type type) - + internal static List GetMembersThatNeedToBeSet(Service service, Table table, Type type) { var properties = (from property in type.GetProperties() from row in table.Rows - where TheseTypesMatch(type, property.PropertyType, row) + where TheseTypesMatch(service, type, property.PropertyType, row) && IsMemberMatchingToColumnName(property, row.Id()) - select new MemberHandler { Type = type, Row = row, MemberName = property.Name, PropertyType = property.PropertyType, Setter = (i, v) => property.SetValue(i, v, null) }).ToList(); + select new MemberHandler { Type = type, Row = row, MemberName = property.Name, PropertyType = property.PropertyType, Setter = (i, v) => property.SetValue(i, v, null) }) + .ToList(); var fieldInfos = type.GetFields(); var fields = (from field in fieldInfos from row in table.Rows - where TheseTypesMatch(type, field.FieldType, row) + where TheseTypesMatch(service, type, field.FieldType, row) && IsMemberMatchingToColumnName(field, row.Id()) select new MemberHandler { Type = type, Row = row, MemberName = field.Name, PropertyType = field.FieldType, Setter = (i, v) => field.SetValue(i, v) }).ToList(); @@ -159,16 +159,17 @@ where TheseTypesMatch(type, field.FieldType, row) var field = fieldInfos[index]; var row = table.Rows[index]; - if (TheseTypesMatch(type, field.FieldType, row)) + if (TheseTypesMatch(service, type, field.FieldType, row)) { - memberHandlers.Add(new MemberHandler - { - Type = type, - Row = row, - MemberName = field.Name, - PropertyType = field.FieldType, - Setter = (i, v) => field.SetValue(i, v) - }); + memberHandlers.Add( + new MemberHandler + { + Type = type, + Row = row, + MemberName = field.Name, + PropertyType = field.FieldType, + Setter = (i, v) => field.SetValue(i, v) + }); } } } @@ -183,22 +184,26 @@ private static bool IsMatchingAlias(MemberInfo field, string id) return aliases.Any(a => a.Aliases.Any(al => Regex.Match(id, al).Success)); } - private static bool TheseTypesMatch(Type targetType, Type memberType, DataTableRow row) + private static bool TheseTypesMatch(Service service, Type targetType, Type memberType, DataTableRow row) { - return Service.Instance.GetValueRetrieverFor(row, targetType, memberType) != null; + return service.GetValueRetrieverFor(row, targetType, memberType) != null; } internal class MemberHandler { public DataTableRow Row { get; set; } + public string MemberName { get; set; } + public Action Setter { get; set; } + public Type Type { get; set; } + public Type PropertyType { get; set; } - public object GetValue() + public object GetValue(Service service) { - var valueRetriever = Service.Instance.GetValueRetrieverFor(Row, Type, PropertyType); + var valueRetriever = service.GetValueRetrieverFor(Row, Type, PropertyType); return valueRetriever.Retrieve(new KeyValuePair(Row[0], Row[1]), Type, PropertyType); } } @@ -217,8 +222,7 @@ private static Table FlipThisHorizontalTableToAVerticalTable(Table table) private static bool ThisIsAVerticalTable(Table table, Type type) { - if (TheHeaderIsTheOldFieldValuePair(table)) - return true; + if (TheHeaderIsTheOldFieldValuePair(table)) return true; return (table.Rows.Count() != 1) || (table.Header.Count == 2 && TheFirstRowValueIsTheNameOfAProperty(table, type)); } @@ -234,13 +238,11 @@ private static bool TheFirstRowValueIsTheNameOfAProperty(Table table, Type type) .Any(property => IsMemberMatchingToColumnName(property, firstRowValue)); } - public static bool IsValueTupleType(Type type, bool checkBaseTypes = false) + private static bool IsValueTupleType(Type type, bool checkBaseTypes = false) { - if (type == null) - throw new ArgumentNullException(nameof(type)); + if (type == null) throw new ArgumentNullException(nameof(type)); - if (type == typeof(Tuple)) - return true; + if (type == typeof(Tuple)) return true; while (type != null) { @@ -262,8 +264,7 @@ public static bool IsValueTupleType(Type type, bool checkBaseTypes = false) return true; } - if (!checkBaseTypes) - break; + if (!checkBaseTypes) break; type = type.BaseType; } diff --git a/Reqnroll/Assist/TableExtensionMethods.cs b/Reqnroll/Assist/TableExtensionMethods.cs index b3b75cc86..09de0a359 100644 --- a/Reqnroll/Assist/TableExtensionMethods.cs +++ b/Reqnroll/Assist/TableExtensionMethods.cs @@ -5,7 +5,7 @@ // ReSharper disable once CheckNamespace namespace Reqnroll { - public static class TableHelperExtensionMethods + public static class TableExtensionMethods { public static T CreateInstance(this Table table) { @@ -16,8 +16,8 @@ public static T CreateInstance(this Table table, InstanceCreationOptions crea { var instanceTable = TEHelpers.GetTheProperInstanceTable(table, typeof(T)); return TEHelpers.ThisTypeHasADefaultConstructor() - ? TEHelpers.CreateTheInstanceWithTheDefaultConstructor(instanceTable, creationOptions) - : TEHelpers.CreateTheInstanceWithTheValuesFromTheTable(instanceTable, creationOptions); + ? TEHelpers.CreateTheInstanceWithTheDefaultConstructor(Service.Instance, instanceTable, creationOptions) + : TEHelpers.CreateTheInstanceWithTheValuesFromTheTable(Service.Instance, instanceTable, creationOptions); } public static T CreateInstance(this Table table, Func methodToCreateTheInstance) @@ -40,7 +40,7 @@ public static void FillInstance(this Table table, object instance) public static void FillInstance(this Table table, object instance, InstanceCreationOptions creationOptions) { var instanceTable = TEHelpers.GetTheProperInstanceTable(table, instance.GetType()); - TEHelpers.LoadInstanceWithKeyValuePairs(instanceTable, instance, creationOptions); + TEHelpers.LoadInstanceWithKeyValuePairs(Service.Instance, instanceTable, instance, creationOptions); } public static IEnumerable CreateSet(this Table table) @@ -86,6 +86,7 @@ public static IEnumerable CreateSet(this Table table, Func methodToCrea return list; } + public static IEnumerable CreateSet(this Table table, Func methodToCreateEachInstance) { return CreateSet(table, methodToCreateEachInstance, null); diff --git a/Reqnroll/Assist/TableHelpers.cs b/Reqnroll/Assist/TableHelpers.cs new file mode 100644 index 000000000..6dfa2cb6d --- /dev/null +++ b/Reqnroll/Assist/TableHelpers.cs @@ -0,0 +1,214 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; +using Reqnroll.Assist.Attributes; + +namespace Reqnroll.Assist; + +public class TableHelpers +{ + private readonly Service _service; + + public TableHelpers(Service service) + { + _service = service; + } + + public IEnumerable CreateSet(Table table) + { + return CreateSet(table, null); + } + + public IEnumerable CreateSet(Table table, InstanceCreationOptions creationOptions) + { + int count = table.Rows.Count; + + var list = new List(count); + + var pivotTable = new PivotTable(table); + for (var index = 0; index < count; index++) + { + var instanceTable = pivotTable.GetInstanceTable(index); + var instance = CreateInstance(instanceTable, creationOptions); + list.Add(instance); + } + + return list; + } + + public T CreateInstance(Table table) + { + var instanceTable = TEHelpers.GetTheProperInstanceTable(table, typeof(T)); + return TEHelpers.ThisTypeHasADefaultConstructor() + ? TEHelpers.CreateTheInstanceWithTheDefaultConstructor(_service, instanceTable, null) + : TEHelpers.CreateTheInstanceWithTheValuesFromTheTable(_service, instanceTable, null); + } + + public T CreateInstance(Table table, InstanceCreationOptions creationOptions) + { + var instanceTable = TEHelpers.GetTheProperInstanceTable(table, typeof(T)); + return TEHelpers.ThisTypeHasADefaultConstructor() + ? TEHelpers.CreateTheInstanceWithTheDefaultConstructor(_service, instanceTable, creationOptions) + : TEHelpers.CreateTheInstanceWithTheValuesFromTheTable(_service, instanceTable, creationOptions); + } + + public T CreateInstance(Table table, Func methodToCreateTheInstance) + { + return CreateInstance(table, methodToCreateTheInstance, null); + } + + public T CreateInstance(Table table, Func methodToCreateTheInstance, InstanceCreationOptions creationOptions) + { + var instance = methodToCreateTheInstance(); + FillInstance(table, instance, creationOptions); + return instance; + } + + public void FillInstance(Table table, object instance, InstanceCreationOptions creationOptions) + { + var instanceTable = TEHelpers.GetTheProperInstanceTable(table, instance.GetType()); + TEHelpers.LoadInstanceWithKeyValuePairs(_service, instanceTable, instance, creationOptions); + } + + /// + /// Indicates whether the table is equivalent to the specified instance by comparing the values of all + /// columns against the properties of the instance. Will return false after finding the first difference. + /// + public bool IsEquivalentToInstance(Table table, T instance) + { + AssertThatTheInstanceExists(instance); + + var instanceTable = TEHelpers.GetTheProperInstanceTable(table, typeof(T)); + + return HasDifference(_service, instanceTable, instance) == false; + } + + public void CompareToInstance(Table table, T instance) + { + AssertThatTheInstanceExists(instance); + + var instanceTable = TEHelpers.GetTheProperInstanceTable(table, typeof(T)); + + var differences = FindAnyDifferences(_service, instanceTable, instance); + + if (differences.Any()) throw new ComparisonException(CreateDescriptiveErrorMessage(differences)); + } + + private Difference[] FindAnyDifferences(Service service, Table table, T instance) + { + return (from row in table.Rows + where ThePropertyDoesNotExist(instance, row) || TheValuesDoNotMatch(instance, row) + select CreateDifferenceForThisRow(service, instance, row)).ToArray(); + } + + private abstract class Difference + { + public abstract string Description { get; } + } + + private class PropertyDoesNotExist : Difference + { + private readonly string propertyName; + + public PropertyDoesNotExist(string propertyName) + { + this.propertyName = propertyName; + } + + public override string Description => + $"{propertyName}: Property does not exist"; + } + + private class PropertyDiffers : Difference + { + private readonly string propertyName; + private readonly object expected; + private readonly object actual; + private readonly IValueComparer comparer; + + public PropertyDiffers(string propertyName, object expected, object actual, IValueComparer comparer) + { + this.propertyName = propertyName; + this.expected = expected; + this.actual = actual; + this.comparer = comparer; + } + + public override string Description => + $"{propertyName}: Expected <{expected}>, Actual <{actual}>, Using '{comparer.GetType().FullName}'"; + } + + private static string CreateDescriptiveErrorMessage(IEnumerable differences) + { + return differences.Aggregate( + @"The following fields did not match:", + (sum, next) => sum + (Environment.NewLine + next.Description)); + } + + private Difference CreateDifferenceForThisRow(Service service, T instance, DataTableRow row) + { + var propertyName = row.Id(); + + if (ThePropertyDoesNotExist(instance, row)) return new PropertyDoesNotExist(propertyName); + + var expected = row.Value(); + var actual = instance.GetPropertyValue(propertyName); + var comparer = FindValueComparerForValue(instance.GetPropertyValue(propertyName)); + return new PropertyDiffers(propertyName, expected, actual, comparer); + } + + internal bool ThePropertyDoesNotExist(T instance, DataTableRow row) + { + return instance.GetType() + .GetProperties() + .Any(property => IsMemberMatchingToColumnName(property, row.Id())) + == false; + } + + internal static bool IsMemberMatchingToColumnName(MemberInfo member, string columnName) + { + return member.Name.MatchesThisColumnName(columnName) + || IsMatchingAlias(member, columnName); + } + + private static bool IsMatchingAlias(MemberInfo field, string id) + { + var aliases = field.GetCustomAttributes().OfType(); + return aliases.Any(a => a.Aliases.Any(al => Regex.Match(id, al).Success)); + } + + private bool TheValuesDoNotMatch(T instance, DataTableRow row) + { + var expected = GetTheExpectedValue(row); + var propertyValue = instance.GetPropertyValue(row.Id()); + var comparer = FindValueComparerForValue(propertyValue); + + return comparer + .Compare(expected, propertyValue) + == false; + } + + private IValueComparer FindValueComparerForValue(object propertyValue) => + _service.ValueComparers.FirstOrDefault(x => x.CanCompare(propertyValue)); + + private static string GetTheExpectedValue(DataTableRow row) + { + return row.Value(); + } + + private static void AssertThatTheInstanceExists(T instance) + { + if (instance == null) throw new ComparisonException("The item to compare was null."); + } + + private bool HasDifference(Service service, Table table, T instance) + { + // This method exists so it will stop evaluating the instance (hence stop using Reflection) + // after the first difference is found. + return (from row in table.Rows + select row) + .Any(row => ThePropertyDoesNotExist(instance, row) || TheValuesDoNotMatch(instance, row)); + } +} diff --git a/Reqnroll/Assist/ValueRetrievers/ArrayValueRetriever.cs b/Reqnroll/Assist/ValueRetrievers/ArrayValueRetriever.cs index 611ac3b02..2f119cc21 100644 --- a/Reqnroll/Assist/ValueRetrievers/ArrayValueRetriever.cs +++ b/Reqnroll/Assist/ValueRetrievers/ArrayValueRetriever.cs @@ -6,6 +6,10 @@ namespace Reqnroll.Assist.ValueRetrievers { public class ArrayValueRetriever : EnumerableValueRetriever { + public ArrayValueRetriever(Service service) : base(service) + { + } + public override bool CanRetrieve(KeyValuePair keyValuePair, Type targetType, Type propertyType) { return propertyType.IsArray; @@ -24,7 +28,8 @@ protected override object BuildInstance(int count, IEnumerable values, Type valu { typedArray.SetValue(value, i++); } + return typedArray; } } -} \ No newline at end of file +} diff --git a/Reqnroll/Assist/ValueRetrievers/EnumerableValueRetriever.cs b/Reqnroll/Assist/ValueRetrievers/EnumerableValueRetriever.cs index 30a3bdacf..2a6da0c0e 100644 --- a/Reqnroll/Assist/ValueRetrievers/EnumerableValueRetriever.cs +++ b/Reqnroll/Assist/ValueRetrievers/EnumerableValueRetriever.cs @@ -7,8 +7,14 @@ namespace Reqnroll.Assist.ValueRetrievers { public abstract class EnumerableValueRetriever : IValueRetriever { + private readonly Service _service; private static readonly char[] Separators = { ',', ';' }; + public EnumerableValueRetriever(Service service) + { + _service = service; + } + public abstract bool CanRetrieve(KeyValuePair keyValuePair, Type targetType, Type propertyType); public object Retrieve(KeyValuePair keyValuePair, Type targetType, Type propertyType) @@ -48,9 +54,9 @@ private IEnumerable GetItems(string[] strings, KeyValuePair keyV protected abstract object BuildInstance(int count, IEnumerable values, Type valueType); - private static IValueRetriever GetValueRetriever(KeyValuePair keyValuePair, Type targetType, Type valueType) + private IValueRetriever GetValueRetriever(KeyValuePair keyValuePair, Type targetType, Type valueType) { - foreach (var retriever in Service.Instance.ValueRetrievers) + foreach (var retriever in _service.ValueRetrievers) { if (retriever.CanRetrieve(keyValuePair, targetType, valueType)) { diff --git a/Reqnroll/Assist/ValueRetrievers/ListValueRetriever.cs b/Reqnroll/Assist/ValueRetrievers/ListValueRetriever.cs index ce218bcd3..abb916dec 100644 --- a/Reqnroll/Assist/ValueRetrievers/ListValueRetriever.cs +++ b/Reqnroll/Assist/ValueRetrievers/ListValueRetriever.cs @@ -10,6 +10,10 @@ public class ListValueRetriever : EnumerableValueRetriever { private MethodInfo toListMethodInfo; + public ListValueRetriever(Service service) : base(service) + { + } + public override bool CanRetrieve(KeyValuePair keyValuePair, Type targetType, Type propertyType) { if (!propertyType.IsGenericType) diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/CreateInstanceHelperMethodTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/CreateInstanceHelperMethodTests.cs index 50a8b685e..68cd1d9a4 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/CreateInstanceHelperMethodTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/CreateInstanceHelperMethodTests.cs @@ -11,6 +11,7 @@ namespace Reqnroll.RuntimeTests.AssistTests { + [Obsolete] public class CreateInstanceHelperMethodTests { public CreateInstanceHelperMethodTests() diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/FindAllInSetExtensionMethodsTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/FindAllInSetExtensionMethodsTests.cs index 541ceae8f..a0b55a06d 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/FindAllInSetExtensionMethodsTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/FindAllInSetExtensionMethodsTests.cs @@ -11,6 +11,7 @@ namespace Reqnroll.RuntimeTests.AssistTests { + [Obsolete] public class FindAllInSetExtensionMethodsTests { private IList testSet; diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/FindInSetExtensionMethodTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/FindInSetExtensionMethodTests.cs index 71604cd24..5f5086512 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/FindInSetExtensionMethodTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/FindInSetExtensionMethodTests.cs @@ -10,6 +10,7 @@ namespace Reqnroll.RuntimeTests.AssistTests { + [Obsolete] public class FindInSetExtensionMethodsTests { private IList testSet; diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/InstanceComparisonExtensionMethodsTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/InstanceComparisonExtensionMethodsTests.cs index 2679c4375..dba761024 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/InstanceComparisonExtensionMethodsTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/InstanceComparisonExtensionMethodsTests.cs @@ -3,12 +3,12 @@ using System.Threading; using Xunit; using FluentAssertions; -using Reqnroll.Assist; using Reqnroll.RuntimeTests.AssistTests.TestInfrastructure; namespace Reqnroll.RuntimeTests.AssistTests { + [Obsolete] public class InstanceComparisonExtensionMethodsTests { public InstanceComparisonExtensionMethodsTests() diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/InstanceEquivalenceExtensionMethodTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/InstanceEquivalenceExtensionMethodTests.cs index ae672bedc..9d7776ac1 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/InstanceEquivalenceExtensionMethodTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/InstanceEquivalenceExtensionMethodTests.cs @@ -9,6 +9,7 @@ namespace Reqnroll.RuntimeTests.AssistTests { + [Obsolete] public class InstanceEquivalenceExtensionMethodTests { public InstanceEquivalenceExtensionMethodTests() diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/ProjectionTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/ProjectionTests.cs index 3aa990297..9e2726622 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/ProjectionTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/ProjectionTests.cs @@ -10,7 +10,7 @@ namespace Reqnroll.RuntimeTests.AssistTests { - + [Obsolete] public class ProjectionTests { private SetComparisonTestObject testInstance; diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/RowExtensionMethodTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/RowExtensionMethodTests.cs index 9f2437699..606fec113 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/RowExtensionMethodTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/RowExtensionMethodTests.cs @@ -10,6 +10,7 @@ namespace Reqnroll.RuntimeTests.AssistTests { + [Obsolete] public class RowExtensionMethodTests { public RowExtensionMethodTests() diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/SetComparisonExtensionMethods_MessageTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/SetComparisonExtensionMethods_MessageTests.cs index a04ecb218..2b2eb0164 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/SetComparisonExtensionMethods_MessageTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/SetComparisonExtensionMethods_MessageTests.cs @@ -9,6 +9,7 @@ namespace Reqnroll.RuntimeTests.AssistTests { + [Obsolete] public abstract class SetComparisonExtensionMethods_MessageTests { [Fact] @@ -16,12 +17,14 @@ public void Returns_the_names_of_any_fields_that_do_not_exist() { var table = new Table("StringProperty", "AFieldThatDoesNotExist", "AnotherFieldThatDoesNotExist"); - var items = new[] {new SetComparisonTestObject()}; + var items = new[] { new SetComparisonTestObject() }; var exception = GetTheExceptionThrowByComparingThese(table, items); - exception.Message.AgnosticLineBreak().Should().Be( - @"The following fields do not exist: + exception.Message.AgnosticLineBreak() + .Should() + .Be( + @"The following fields do not exist: AFieldThatDoesNotExist AnotherFieldThatDoesNotExist".AgnosticLineBreak()); } @@ -31,12 +34,14 @@ public void Returns_descriptive_message_when_one_result_exists_but_there_should_ { var table = new Table("StringProperty"); - var items = new[] {new SetComparisonTestObject()}; + var items = new[] { new SetComparisonTestObject() }; var exception = GetTheExceptionThrowByComparingThese(table, items); - exception.Message.AgnosticLineBreak().Should().Be( - @" + exception.Message.AgnosticLineBreak() + .Should() + .Be( + @" | StringProperty | + | | ".AgnosticLineBreak()); @@ -47,12 +52,14 @@ public void Returns_descriptive_message_when_two_results_exist_but_there_should_ { var table = new Table("StringProperty"); - var items = new[] {new SetComparisonTestObject(), new SetComparisonTestObject()}; + var items = new[] { new SetComparisonTestObject(), new SetComparisonTestObject() }; var exception = GetTheExceptionThrowByComparingThese(table, items); - exception.Message.AgnosticLineBreak().Should().Be( - @" + exception.Message.AgnosticLineBreak() + .Should() + .Be( + @" | StringProperty | + | | + | | @@ -65,12 +72,14 @@ public void Returns_1_as_the_missing_item_when_only_one_item_exists() var table = new Table("StringProperty"); table.AddRow("orange"); - var items = new[] {new SetComparisonTestObject {StringProperty = "apple"}}; + var items = new[] { new SetComparisonTestObject { StringProperty = "apple" } }; var exception = GetTheExceptionThrowByComparingThese(table, items); - exception.Message.AgnosticLineBreak().Should().Be( -@" + exception.Message.AgnosticLineBreak() + .Should() + .Be( + @" | StringProperty | - | orange | + | apple | @@ -85,15 +94,17 @@ public void Returns_2_as_the_missing_item_when_the_second_item_does_not_match() table.AddRow("apple"); var items = new[] - { - new SetComparisonTestObject {StringProperty = "orange"}, - new SetComparisonTestObject {StringProperty = "rotten apple"} - }; + { + new SetComparisonTestObject { StringProperty = "orange" }, + new SetComparisonTestObject { StringProperty = "rotten apple" } + }; var exception = GetTheExceptionThrowByComparingThese(table, items); - exception.Message.AgnosticLineBreak().Should().Be( - @" + exception.Message.AgnosticLineBreak() + .Should() + .Be( + @" | StringProperty | | orange | - | apple | @@ -109,15 +120,18 @@ public void Returns_a_descriptive_error_when_three_results_exist_when_two_expect table.AddRow("apple"); var items = new[] - { - new SetComparisonTestObject {StringProperty = "orange"}, - new SetComparisonTestObject {StringProperty = "apple"}, - new SetComparisonTestObject {StringProperty = "extra row"} - }; + { + new SetComparisonTestObject { StringProperty = "orange" }, + new SetComparisonTestObject { StringProperty = "apple" }, + new SetComparisonTestObject { StringProperty = "extra row" } + }; var exception = GetTheExceptionThrowByComparingThese(table, items); - exception.Message.AgnosticLineBreak().Should().Be(@" + exception.Message.AgnosticLineBreak() + .Should() + .Be( + @" | StringProperty | | orange | | apple | @@ -132,15 +146,18 @@ public void Returns_a_descriptive_error_when_three_results_exist_when_one_expect table.AddRow("orange"); var items = new[] - { - new SetComparisonTestObject {StringProperty = "orange"}, - new SetComparisonTestObject {StringProperty = "apple"}, - new SetComparisonTestObject {StringProperty = "banana"} - }; + { + new SetComparisonTestObject { StringProperty = "orange" }, + new SetComparisonTestObject { StringProperty = "apple" }, + new SetComparisonTestObject { StringProperty = "banana" } + }; var exception = GetTheExceptionThrowByComparingThese(table, items); - exception.Message.AgnosticLineBreak().Should().Be(@" + exception.Message.AgnosticLineBreak() + .Should() + .Be( + @" | StringProperty | | orange | + | apple | @@ -158,7 +175,10 @@ public void Returns_a_descriptive_error_when_no_results_exist_when_one_expected( var exception = GetTheExceptionThrowByComparingThese(table, items); - exception.Message.AgnosticLineBreak().Should().Be(@" + exception.Message.AgnosticLineBreak() + .Should() + .Be( + @" | StringProperty | - | orange | ".AgnosticLineBreak()); @@ -185,7 +205,10 @@ public void Includes_milliseconds_and_ticks_in_error_for_date_time_fields() var exception = GetTheExceptionThrowByComparingThese(table, items); - exception.Message.AgnosticLineBreak().Should().Be(@" + exception.Message.AgnosticLineBreak() + .Should() + .Be( + @" | DateTimeProperty | - | 3/28/2018 12:34:56 AM | + | 3/28/2018 12:34:56.0780009 AM | @@ -202,13 +225,14 @@ protected ComparisonException GetTheExceptionThrowByComparingThese(Table table, { return ex; } + return null; } protected abstract void CallComparison(Table table, SetComparisonTestObject[] items); } - + [Obsolete] public class SetComparisonExtensionMethods_OrderInsensitive_MessageTests : SetComparisonExtensionMethods_MessageTests { [Fact] @@ -219,15 +243,17 @@ public void Returns_both_1_and_two_as_the_missing_items_when_both_cannot_be_foun table.AddRow("apple"); var items = new[] - { - new SetComparisonTestObject {StringProperty = "rotten orange"}, - new SetComparisonTestObject {StringProperty = "rotten apple"} - }; + { + new SetComparisonTestObject { StringProperty = "rotten orange" }, + new SetComparisonTestObject { StringProperty = "rotten apple" } + }; var exception = GetTheExceptionThrowByComparingThese(table, items); - exception.Message.AgnosticLineBreak().Should().Be( - @" + exception.Message.AgnosticLineBreak() + .Should() + .Be( + @" | StringProperty | - | orange | - | apple | @@ -242,7 +268,7 @@ protected override void CallComparison(Table table, SetComparisonTestObject[] it } } - + [Obsolete] public class SetComparisonExtensionMethods_OrderSensitive_MessageTests : SetComparisonExtensionMethods_MessageTests { [Fact] @@ -253,15 +279,17 @@ public void Returns_both_1_and_two_as_the_missing_items_when_both_cannot_be_foun table.AddRow("apple"); var items = new[] - { - new SetComparisonTestObject {StringProperty = "rotten orange"}, - new SetComparisonTestObject {StringProperty = "rotten apple"} - }; + { + new SetComparisonTestObject { StringProperty = "rotten orange" }, + new SetComparisonTestObject { StringProperty = "rotten apple" } + }; var exception = GetTheExceptionThrowByComparingThese(table, items); - exception.Message.AgnosticLineBreak().Should().Be( - @" + exception.Message.AgnosticLineBreak() + .Should() + .Be( + @" | StringProperty | - | orange | + | rotten orange | @@ -275,4 +303,4 @@ protected override void CallComparison(Table table, SetComparisonTestObject[] it table.CompareToSet(items, sequentialEquality: true); } } -} \ No newline at end of file +} diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/SetComparisonExtensionMethods_ThrowTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/SetComparisonExtensionMethods_ThrowTests.cs index 15101f462..9a4afb9c8 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/SetComparisonExtensionMethods_ThrowTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/SetComparisonExtensionMethods_ThrowTests.cs @@ -8,6 +8,7 @@ namespace Reqnroll.RuntimeTests.AssistTests { + [Obsolete] public abstract class SetComparisonExtensionMethods_ThrowTests { public SetComparisonExtensionMethods_ThrowTests() @@ -376,6 +377,7 @@ protected ComparisonTestResult DetermineIfExceptionWasThrownByComparingThese( } + [Obsolete] public class SetComparisonExtensionMethods_OrderInsensitive_ThrowTests : SetComparisonExtensionMethods_ThrowTests { [Fact] @@ -405,6 +407,7 @@ protected override void CallComparison(Table table, T[] items) } + [Obsolete] public class SetComparisonExtensionMethods_OrderSensitive_ThrowTests : SetComparisonExtensionMethods_ThrowTests { [Fact] diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/SituationalTests/ListOfNullablesWithCustomNullValueRetrieverTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/SituationalTests/ListOfNullablesWithCustomNullValueRetrieverTests.cs index d9250850e..24e2dc0bb 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/SituationalTests/ListOfNullablesWithCustomNullValueRetrieverTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/SituationalTests/ListOfNullablesWithCustomNullValueRetrieverTests.cs @@ -27,9 +27,10 @@ public class ListOfNullablesWithCustomNullValueRetrieverTests [Fact] public void CanRetrieveAListThatContainsValuesThatShouldBeRetrievedByACustomValueRetriever() { - Service.Instance.ValueRetrievers.Register(new NullValueRetriever("")); + var service = new Service(); + service.ValueRetrievers.Register(new NullValueRetriever("")); - var retriever_under_test = Service.Instance.GetValueRetrieverFor(testRow, typeof(object), typeof(IList>)); + var retriever_under_test = service.GetValueRetrieverFor(testRow, typeof(object), typeof(IList>)); retriever_under_test.Should().NotBeNull(); var can = retriever_under_test.CanRetrieve(Val, typeof(IList>)); @@ -63,13 +64,17 @@ public static IEnumerable EnumerableRetrieverWithNullableValueRetrieve [MemberData(nameof(EnumerableRetrieverWithNullableValueRetriever_TestCases))] public void IntegrationOfEnumerableRetrieverWithNullableValueRetriever(string input, IEnumerable expectedValues) { - Service.Instance.ValueRetrievers.Register(new NullValueRetriever("")); + var service = new Service(); + service.ValueRetrievers.Register(new NullValueRetriever("")); + + var tableHelpers = new TableHelpers(service); + var table = new Table("Field", "Value"); table.AddRow("MyExampleValues", input); var expected = expectedValues.ToList(); - var test = table.CreateInstance(); + var test = tableHelpers.CreateInstance(table); test.MyExampleValues.Should().BeEquivalentTo(expected); diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/SituationalTests/NullableEnumTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/SituationalTests/NullableEnumTests.cs index 1b1d54850..f0ea30871 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/SituationalTests/NullableEnumTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/SituationalTests/NullableEnumTests.cs @@ -23,39 +23,51 @@ public class TestEntity [Fact] public void The_value_should_be_set_if_it_is_in_the_table() { + var service = new Service(); + var tableHelpers = new TableHelpers(service); + var table = new Table("Field", "Value"); table.AddRow("TestProperty", "Value2"); - var test = table.CreateInstance(); + var test = tableHelpers.CreateInstance(table); test.TestProperty.Should().Be(TestEnum.Value2); } [Fact] public void The_value_should_be_NULL_if_it_is_not_filled_in_the_table() { + var service = new Service(); + var tableHelpers = new TableHelpers(service); + var table = new Table("Field", "Value"); table.AddRow("TestProperty", ""); - var test = table.CreateInstance(); + var test = tableHelpers.CreateInstance(table); test.TestProperty.Should().BeNull(); } [Fact] public void The_value_should_be_NULL_if_it_is_not_in_the_table() { + var service = new Service(); + var tableHelpers = new TableHelpers(service); + var table = new Table("Field", "Value"); - var test = table.CreateInstance(); + var test = tableHelpers.CreateInstance(table); test.TestProperty.Should().BeNull(); } [Fact] public void There_should_be_an_error_if_in_the_table_is_no_valid_Enum_value() { + var service = new Service(); + var tableHelpers = new TableHelpers(service); + var table = new Table("Field", "Value"); table.AddRow("TestProperty", "NotAnEnumValue"); - Action x = () => { table.CreateInstance(); }; + Action x = () => { tableHelpers.CreateInstance(table); }; x.Should().Throw(); } diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTestBase.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTestBase.cs index 09c94fcfd..b41f94a14 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTestBase.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTestBase.cs @@ -7,7 +7,6 @@ namespace Reqnroll.RuntimeTests.AssistTests.TableHelperExtensionMethods { - public abstract class CreateInstanceHelperMethodTestBase { private readonly Func func; @@ -145,4 +144,4 @@ public virtual void Sets_char_values() person.NullableChar.Should().Be('S'); } } -} \ No newline at end of file +} diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests.cs index cb0c58dce..edd5b479d 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests.cs @@ -1,3 +1,4 @@ +using System; using FluentAssertions; using Xunit; using Reqnroll.Assist; @@ -6,6 +7,7 @@ namespace Reqnroll.RuntimeTests.AssistTests.TableHelperExtensionMethods { + [Obsolete] public class CreateInstanceHelperMethodTests : CreateInstanceHelperMethodTestBase { public CreateInstanceHelperMethodTests() diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithArrayOfEnums.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithArrayOfEnums.cs index 91e1aa95c..bbab6d1b4 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithArrayOfEnums.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithArrayOfEnums.cs @@ -1,3 +1,4 @@ +using System; using FluentAssertions; using Reqnroll.Assist; using Reqnroll.RuntimeTests.AssistTests.ExampleEntities; @@ -5,6 +6,7 @@ namespace Reqnroll.RuntimeTests.AssistTests.TableHelperExtensionMethods { + [Obsolete] public class CreateInstanceHelperMethodTests_WithArrayOfEnums { [Fact] diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithArrayOfValues.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithArrayOfValues.cs index d318232cb..e3da85301 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithArrayOfValues.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithArrayOfValues.cs @@ -1,3 +1,4 @@ +using System; using FluentAssertions; using Reqnroll.Assist; using Reqnroll.RuntimeTests.AssistTests.ExampleEntities; @@ -5,6 +6,7 @@ namespace Reqnroll.RuntimeTests.AssistTests.TableHelperExtensionMethods { + [Obsolete] public class CreateInstanceHelperMethodTests_WithArrayOfValues { diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithFunc.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithFunc.cs index dc0575527..af5be8dc0 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithFunc.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithFunc.cs @@ -1,3 +1,4 @@ +using System; using Xunit; using FluentAssertions; using Reqnroll.Assist; @@ -6,6 +7,7 @@ namespace Reqnroll.RuntimeTests.AssistTests.TableHelperExtensionMethods { + [Obsolete] public class CreateInstanceHelperMethodTests_WithFunc { [Fact] diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithListOfEnums.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithListOfEnums.cs index 09cbf351e..7ca692f31 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithListOfEnums.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithListOfEnums.cs @@ -1,3 +1,4 @@ +using System; using FluentAssertions; using Reqnroll.Assist; using Reqnroll.RuntimeTests.AssistTests.ExampleEntities; @@ -5,6 +6,7 @@ namespace Reqnroll.RuntimeTests.AssistTests.TableHelperExtensionMethods { + [Obsolete] public class CreateInstanceHelperMethodTests_WithListOfEnums { [Fact] diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithListOfValues.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithListOfValues.cs index 8358496cb..fad1b43c9 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithListOfValues.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperMethodTests_WithListOfValues.cs @@ -1,3 +1,4 @@ +using System; using FluentAssertions; using Reqnroll.Assist; using Reqnroll.RuntimeTests.AssistTests.ExampleEntities; @@ -5,6 +6,7 @@ namespace Reqnroll.RuntimeTests.AssistTests.TableHelperExtensionMethods { + [Obsolete] public class CreateInstanceHelperMethodTests_WithListOfValues { [Fact] diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperStandardTypesTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperStandardTypesTests.cs index 5736137de..4819b4d2b 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperStandardTypesTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateInstanceHelperStandardTypesTests.cs @@ -9,6 +9,7 @@ namespace Reqnroll.RuntimeTests.AssistTests.TableHelperExtensionMethods { + [Obsolete] public class CreateInstanceHelperStandardTypesTests { public CreateInstanceHelperStandardTypesTests() diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests.cs index 37ae94e46..f9b83fe73 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests.cs @@ -10,6 +10,7 @@ namespace Reqnroll.RuntimeTests.AssistTests.TableHelperExtensionMethods { + [Obsolete] public class CreateSetHelperMethodTests { public CreateSetHelperMethodTests() diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests_WithFunc.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests_WithFunc.cs index a68532217..3816f0b6a 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests_WithFunc.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests_WithFunc.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -10,6 +11,7 @@ namespace Reqnroll.RuntimeTests.AssistTests.TableHelperExtensionMethods { + [Obsolete] public class CreateSetHelperMethodTests_WithFunc { public CreateSetHelperMethodTests_WithFunc() diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests_WithFuncAndTableRowArgument.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests_WithFuncAndTableRowArgument.cs index 3e694f1f9..16d747025 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests_WithFuncAndTableRowArgument.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests_WithFuncAndTableRowArgument.cs @@ -11,6 +11,7 @@ namespace Reqnroll.RuntimeTests.AssistTests.TableHelperExtensionMethods { + [Obsolete] public class CreateSetHelperMethodTests_WithFuncAndTableRowArgument { public CreateSetHelperMethodTests_WithFuncAndTableRowArgument() diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetWithNullableValuesTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetWithNullableValuesTests.cs index bf8e80ad5..cf75e09b5 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetWithNullableValuesTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetWithNullableValuesTests.cs @@ -10,6 +10,7 @@ namespace Reqnroll.RuntimeTests.AssistTests.TableHelperExtensionMethods { + [Obsolete] public class CreateSetWithNullableValuesTests { public CreateSetWithNullableValuesTests() diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/FillInstanceHelperMethodTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/FillInstanceHelperMethodTests.cs index 943cf5008..ab9e7d941 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/FillInstanceHelperMethodTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelperExtensionMethods/FillInstanceHelperMethodTests.cs @@ -1,3 +1,4 @@ +using System; using FluentAssertions; using Xunit; using Reqnroll.Assist; @@ -6,6 +7,7 @@ namespace Reqnroll.RuntimeTests.AssistTests.TableHelperExtensionMethods { + [Obsolete] public class FillInstanceHelperMethodTests : CreateInstanceHelperMethodTestBase { public FillInstanceHelperMethodTests() diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CompatibilityTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CompatibilityTests.cs new file mode 100644 index 000000000..b69c5afc8 --- /dev/null +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CompatibilityTests.cs @@ -0,0 +1,36 @@ +using System; +using FluentAssertions; +using Reqnroll.Assist; +using Reqnroll.RuntimeTests.AssistTests.ExampleEntities; +using Xunit; + +namespace Reqnroll.RuntimeTests.AssistTests.TableHelpersTests; + +public class CompatibilityTests +{ + [Fact] + [Obsolete("Compatibility tests for Obsolete code")] + public virtual void Create_instance_will_return_an_instance_of_T() + { + var tableHelpers = new TableHelpers(new Service()); + var table = new Table("Field", "Value"); + + var personOld = table.CreateInstance(); + var personNew = tableHelpers.CreateInstance(table); + + personNew.Should().BeEquivalentTo(personOld); + } + + [Fact] + [Obsolete("Compatibility tests for Obsolete code")] + public void Returns_empty_set_of_type_when_there_are_no_rows() + { + var tableHelpers = new TableHelpers(new Service()); + var table = new Table("FirstName"); + + var personOld = table.CreateSet(); + var peopleNew = tableHelpers.CreateSet(table); + + peopleNew.Should().BeEquivalentTo(personOld); + } +} diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CreateInstanceHelperMethodTestBase.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CreateInstanceHelperMethodTestBase.cs new file mode 100644 index 000000000..5702a1818 --- /dev/null +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CreateInstanceHelperMethodTestBase.cs @@ -0,0 +1,151 @@ +using System; +using System.Globalization; +using System.Threading; +using Xunit; +using FluentAssertions; +using Reqnroll.Assist; +using Reqnroll.RuntimeTests.AssistTests.ExampleEntities; + +namespace Reqnroll.RuntimeTests.AssistTests.TableHelpersTests +{ + public abstract class TableHelpersTestBase + { + private readonly Func func; + + protected TableHelpers Sut { get; } + + public TableHelpersTestBase(Func func) + { + this.func = func; + Sut = new TableHelpers(new Service()); + } + + public Person GetThePerson(Table table) + { + return func(Sut, table); + } + + public TableHelpersTestBase() + { + Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", false); + } + + [Fact] + public virtual void Sets_properties_with_different_case() + { + var table = new Table("Field", "Value"); + table.AddRow("firstname", "John"); + + var person = GetThePerson(table); + + person.FirstName.Should().Be("John"); + } + + [Fact] + public virtual void Sets_properties_from_column_names_with_blanks() + { + var table = new Table("Field", "Value"); + table.AddRow("First Name", "John"); + + var person = GetThePerson(table); + + person.FirstName.Should().Be("John"); + } + + [Fact] + public virtual void Sets_string_values() + { + var table = new Table("Field", "Value"); + table.AddRow("FirstName", "John"); + table.AddRow("LastName", "Galt"); + + var person = GetThePerson(table); + + person.FirstName.Should().Be("John"); + person.LastName.Should().Be("Galt"); + } + + [Fact] + public virtual void Sets_enum_values() + { + var table = new Table("Field", "Value"); + table.AddRow("Sex", "Male"); + + var person = GetThePerson(table); + + person.Sex.Should().Be(Sex.Male); + } + + [Fact] + public virtual void Sets_int_values() + { + var table = new Table("Field", "Value"); + table.AddRow("NumberOfIdeas", "3"); + + var person = GetThePerson(table); + + person.NumberOfIdeas.Should().Be(3); + } + + [Fact] + public virtual void Sets_uint_values() + { + var table = new Table("Field", "Value"); + table.AddRow("UnsignedInt", "3"); + + var person = GetThePerson(table); + + person.UnsignedInt.Should().Be(3); + } + + [Fact] + public virtual void Sets_decimal_values() + { + var table = new Table("Field", "Value"); + table.AddRow("Salary", 9.78M.ToString()); + + var person = GetThePerson(table); + + person.Salary.Should().Be(9.78M); + } + + [Fact] + public virtual void Sets_bool_values() + { + var table = new Table("Field", "Value"); + table.AddRow("IsRational", "true"); + + var person = GetThePerson(table); + + person.IsRational.Should().BeTrue(); + } + + [Fact] + public virtual void Sets_datetime_values() + { + Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", false); //CurrentCulture is sometimes reset to de-AT, no idea why + + var table = new Table("Field", "Value"); + table.AddRow("BirthDate", "12/31/2010"); + table.AddRow("NullableDateTime", "11/30/2011"); + + var person = GetThePerson(table); + + person.BirthDate.Should().Be(new DateTime(2010, 12, 31)); + person.NullableDateTime.Should().Be(new DateTime(2011, 11, 30)); + } + + [Fact] + public virtual void Sets_char_values() + { + var table = new Table("Field", "Value"); + table.AddRow("MiddleInitial", "T"); + table.AddRow("NullableChar", "S"); + + var person = GetThePerson(table); + + person.MiddleInitial.Should().Be('T'); + person.NullableChar.Should().Be('S'); + } + } +} diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CreateInstanceHelperMethodTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CreateInstanceHelperMethodTests.cs new file mode 100644 index 000000000..af033a834 --- /dev/null +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CreateInstanceHelperMethodTests.cs @@ -0,0 +1,119 @@ +using FluentAssertions; +using Xunit; +using Reqnroll.RuntimeTests.AssistTests.ExampleEntities; + +namespace Reqnroll.RuntimeTests.AssistTests.TableHelpersTests +{ + public class TableHelpersTests : TableHelpersTestBase + { + public TableHelpersTests() + : base((sut, t) => sut.CreateInstance(t)) + { + } + + [Fact] + public virtual void Create_instance_will_return_an_instance_of_T() + { + var table = new Table("Field", "Value"); + var person = GetThePerson(table); + person.Should().NotBeNull(); + } + + [Fact] + public void Can_create_an_instance_with_similar_enum_values() + { + var table = new Table("Field", "Value"); + table.AddRow("FourthColor", "Green"); + table.AddRow("ThirdColor", "Red"); + table.AddRow("SecondColor", "Red"); + table.AddRow("FirstColor", "Red"); + + var @class = Sut.CreateInstance(table); + + @class.FirstColor.Should().Be(AClassWithMultipleEnums.Color.Red); + @class.SecondColor.Should().Be(AClassWithMultipleEnums.ColorAgain.Red); + @class.ThirdColor.Should().Be(AClassWithMultipleEnums.Color.Red); + @class.FourthColor.Should().Be(AClassWithMultipleEnums.ColorAgain.Green); + } + + [Fact] + public void Can_create_an_instance_with_a_constructor() + { + var table = new Table("Field", "Value"); + table.AddRow("Field2", "Entry2"); + table.AddRow("Field1", "Entry1"); + + var @class = Sut.CreateInstance(table); + + @class.Field1.Should().Be("Entry1"); + @class.Field2.Should().Be("Entry2"); + } + + [Fact] + public void Can_create_an_instance_with_a_constructor_with_default_parameters() + { + var table = new Table("Field", "Value"); + table.AddRow("Field1", "Entry1"); + + var @class = Sut.CreateInstance(table); + + @class.Field1.Should().Be("Entry1"); + @class.Field2.Should().BeNull(); + @class.Field3.Should().Be("Value3"); + } + + public class AClassWithMultipleEnums + { + public Color FirstColor { get; set; } + + public ColorAgain SecondColor { get; set; } + + public Color ThirdColor { get; set; } + + public ColorAgain FourthColor { get; set; } + + public enum Color + { + Red, + Green, + Blue + } + + public enum ColorAgain + { + Red, + Green, + Blue + } + } + + public class AClassWithAConstructor + { + public AClassWithAConstructor(string field1, string field2) + { + Field1 = field1; + Field2 = field2; + } + + public string Field1 { get; } + + public string Field2 { get; } + } + + public class AClassWithAConstructorWithDefaultParameters + { + public AClassWithAConstructorWithDefaultParameters(string field1, string field2, string field3 = "Value3") + { + Field1 = field1; + Field2 = field2; + Field3 = field3; + } + + public string Field1 { get; } + + public string Field2 { get; } + + public string Field3 { get; } + } + } +} diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CreateSetHelperMethodTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CreateSetHelperMethodTests.cs new file mode 100644 index 000000000..34a4019c4 --- /dev/null +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/TableHelpersTests/CreateSetHelperMethodTests.cs @@ -0,0 +1,422 @@ +using System; +using System.Globalization; +using System.Linq; +using System.Threading; +using Xunit; +using FluentAssertions; +using Reqnroll.Assist; +using Reqnroll.RuntimeTests.AssistTests.ExampleEntities; + +namespace Reqnroll.RuntimeTests.AssistTests.TableHelpersTests +{ + public class CreateSetHelperMethodTests + { + private readonly TableHelpers _sut; + + public CreateSetHelperMethodTests() + { + Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", false); + _sut = new TableHelpers(new Service()); + } + + private static Table CreatePersonTableHeaders() + { + return new Table("FirstName", "LastName", "BirthDate", "NumberOfIdeas", "Salary", "IsRational"); + } + + [Fact] + public void Returns_empty_set_of_type_when_there_are_no_rows() + { + var table = new Table("FirstName"); + var people = _sut.CreateSet(table); + people.Count().Should().Be(0); + } + + [Fact] + public void Returns_one_instance_when_there_is_one_row() + { + var table = new Table("FirstName"); + table.AddRow("John"); + var people = _sut.CreateSet(table); + people.Count().Should().Be(1); + } + + [Fact] + public void Sets_properties_with_different_case() + { + var table = new Table("firstname"); + table.AddRow("John"); + var people = _sut.CreateSet(table); + people.First().FirstName.Should().Be("John"); + } + + [Fact] + public void Sets_properties_from_column_names_with_blanks() + { + var table = new Table("first name"); + table.AddRow("John"); + var people = _sut.CreateSet(table); + people.First().FirstName.Should().Be("John"); + } + + [Fact] + public void Sets_properties_from_column_names_with_underscore_to_properties_with_underscore() + { + var table = new Table("With_Underscore"); + table.AddRow("John"); + var people = _sut.CreateSet(table); + people.First().With_Underscore.Should().Be("John"); + } + + [Fact] + public void Sets_properties_from_column_names_to_properties_with_umlaute() + { + var table = new Table("WithUmlauteäöü"); + table.AddRow("John"); + var people = _sut.CreateSet(table); + people.First().WithUmlauteäöü.Should().Be("John"); + } + + [Fact] + public void Sets_properties_from_column_names_to_properties_with_dash() + { + var table = new Table("first-name"); + table.AddRow("John"); + var people = _sut.CreateSet(table); + people.First().FirstName.Should().Be("John"); + } + + [Fact] + public void Returns_two_instances_when_there_are_two_rows() + { + var table = new Table("FirstName"); + table.AddRow("John"); + table.AddRow("Howard"); + var people = _sut.CreateSet(table); + people.Count().Should().Be(2); + } + + [Fact] + public void two_instances_with_unbound_column_throws_ColumnCouldNotBeBoundException_on_verify() + { + var table = new Table("SurName"); + table.AddRow("John"); + table.AddRow("Howard"); + Action act = () => _sut.CreateSet(table, new InstanceCreationOptions { VerifyAllColumnsBound = true }); + + act.Should().Throw(); + } + + [Fact] + public void Sets_string_values_on_the_instance_when_type_is_string() + { + var table = CreatePersonTableHeaders(); + table.AddRow("John", "Galt", "", "", "", ""); + + var people = _sut.CreateSet(table); + + people.First().FirstName.Should().Be("John"); + people.First().LastName.Should().Be("Galt"); + } + + [Fact] + public void Sets_int_values_on_the_instance_when_type_is_int() + { + var table = CreatePersonTableHeaders(); + table.AddRow("", "", "", "3,124", "", ""); + + var people = _sut.CreateSet(table); + + people.First().NumberOfIdeas.Should().Be(3124); + } + + [Fact] + public void Sets_Enum_values_on_the_instance_when_type_is_int() + { + var table = new Table("FirstName", "LastName", "BirthDate", "NumberOfIdeas", "Salary", "IsRational", "Sex"); + table.AddRow("", "", "", "", "", "", "Male"); + + var people = _sut.CreateSet(table); + + people.First().Sex.Should().Be(Sex.Male); + } + + [Fact] + public void Sets_datetime_on_the_instance_when_type_is_datetime() + { + var table = CreatePersonTableHeaders(); + table.AddRow("", "", "4/28/2009", "3", "", ""); + + var people = _sut.CreateSet(table); + + people.First().BirthDate.Should().Be(new DateTime(2009, 4, 28)); + } + + [Fact] + public void Sets_datetime_on_the_instance_when_type_is_datetime_and_culture_is_fr_FR() + { + Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR", false); + + var table = CreatePersonTableHeaders(); + table.AddRow("", "", "28/4/2009", "3", "", ""); + + var people = _sut.CreateSet(table); + + people.First().BirthDate.Should().Be(new DateTime(2009, 4, 28)); + } + + [Fact] + public void Sets_decimal_on_the_instance_when_type_is_decimal() + { + var table = CreatePersonTableHeaders(); + table.AddRow("", "", "4/28/2009", "3", 9997.43M.ToString(), ""); + + var people = _sut.CreateSet(table); + + people.First().Salary.Should().Be(9997.43M); + } + + [Fact] + public void Sets_bools_on_the_instance_when_type_is_bool() + { + var table = CreatePersonTableHeaders(); + table.AddRow("", "", "4/28/2009", "3", "", "true"); + + var people = _sut.CreateSet(table); + + people.First().IsRational.Should().BeTrue(); + } + + [Fact] + public void Sets_decimals_on_the_instance_when_type_is_decimal() + { + var table = new Table("Salary", "NullableDecimal"); + table.AddRow("4.193", "7.28"); + + var people = _sut.CreateSet(table); + + people.First().Salary.Should().Be(4.193M); + people.First().NullableDecimal.Should().Be(7.28M); + } + + [Fact] + public void Sets_decimals_on_the_instance_when_type_is_decimal_and_culture_is_fr_FR() + { + Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR", false); + + var table = new Table("Salary", "NullableDecimal"); + table.AddRow("4,193", "7,28"); + + var people = _sut.CreateSet(table); + + people.First().Salary.Should().Be(4.193M); + people.First().NullableDecimal.Should().Be(7.28M); + } + + [Fact] + public void Sets_short_on_the_instance_when_type_is_short() + { + var table = new Table("Short", "NullableShort"); + table.AddRow("1234", "1,234"); + + var people = _sut.CreateSet(table); + + people.First().Short.Should().Be(1234); + people.First().NullableShort.Should().Be(1234); + } + + [Fact] + public void Sets_ushort_on_the_instance_when_type_is_ushort() + { + var table = new Table("UShort", "NullableUShort"); + table.AddRow("1234", "1,234"); + + var people = _sut.CreateSet(table); + + people.First().UShort.Should().Be(1234); + people.First().NullableUShort.Value.Should().Be(1234); + } + + [Fact] + public void Sets_longs_on_the_instance_when_type_is_long() + { + var table = new Table("Long", "NullableLong"); + table.AddRow("1234567890123456789", "1,234,567,890,123,456,789"); + + var people = _sut.CreateSet(table); + + people.First().Long.Should().Be(1234567890123456789L); + people.First().NullableLong.Should().Be(1234567890123456789L); + } + + [Fact] + public void Sets_ulongs_on_the_instance_when_type_is_ulong() + { + var table = new Table("ULong", "NullableULong"); + table.AddRow("1234567890123456789", "1,234,567,890,123,456,789"); + + var people = _sut.CreateSet(table); + + people.First().ULong.Should().Be(1234567890123456789UL); + people.First().NullableULong.Should().Be(1234567890123456789UL); + } + + [Fact] + public void Sets_doubles_on_the_instance_when_type_is_double() + { + var table = new Table("Double", "NullableDouble"); + table.AddRow("4.193", "7.28"); + + var people = _sut.CreateSet(table); + + people.First().Double.Should().Be(4.193); + people.First().NullableDouble.Should().Be(7.28); + } + + [Fact] + public void Sets_doubles_on_the_instance_when_type_is_double_and_culture_is_fr_FR() + { + Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR", false); + + var table = new Table("Double", "NullableDouble"); + table.AddRow("4,193", "7,28"); + + var people = _sut.CreateSet(table); + + people.First().Double.Should().Be(4.193); + people.First().NullableDouble.Should().Be(7.28); + } + + [Fact] + public void Sets_bytes_on_the_instance_when_type_is_byte() + { + var table = new Table("Byte", "NullableByte"); + table.AddRow("4.0", "7.0"); + + var people = _sut.CreateSet(table); + + people.First().Byte.Should().Be(4); + people.First().NullableByte.Should().Be(7); + } + + [Fact] + public void Sets_bytes_on_the_instance_when_type_is_byte_and_culture_is_fr_FR() + { + Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR", false); + + var table = new Table("Byte", "NullableByte"); + table.AddRow("4,000", "7,000"); + + var people = _sut.CreateSet(table); + + people.First().Byte.Should().Be(4); + people.First().NullableByte.Should().Be(7); + } + + [Fact] + public void Sets_sbytes_on_the_instance_when_type_is_sbyte() + { + var table = new Table("SByte", "NullableSByte"); + table.AddRow("4.0", "5.0"); + + var people = _sut.CreateSet(table); + + people.First().SByte.Should().Be(4); + people.First().NullableSByte.Value.Should().Be(5); + } + + [Fact] + public void Sets_sbytes_on_the_instance_when_type_is_sbyte_and_culture_is_fr_FR() + { + Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR", false); + + var table = new Table("SByte", "NullableSByte"); + table.AddRow("4,0", "5,0"); + + var people = _sut.CreateSet(table); + + people.First().SByte.Should().Be(4); + people.First().NullableSByte.Value.Should().Be(5); + } + + [Fact] + public void Sets_floats_on_the_instance_when_type_is_float() + { + var table = new Table("Float", "NullableFloat"); + table.AddRow("2.698", "8.954"); + + var people = _sut.CreateSet(table); + + people.First().Float.Should().Be(2.698F); + people.First().NullableFloat.Should().Be(8.954F); + } + + [Fact] + public void Sets_floats_on_the_instance_when_type_is_float_and_culture_is_fr_FR() + { + Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR", false); + + var table = new Table("Float", "NullableFloat"); + table.AddRow("2,698", "8,954"); + + var people = _sut.CreateSet(table); + + people.First().Float.Should().Be(2.698F); + people.First().NullableFloat.Should().Be(8.954F); + } + + [Fact] + public void Sets_guids_on_the_instance_when_the_type_is_guid() + { + var table = new Table("GuidId", "NullableGuidId"); + table.AddRow("8A6F6A2F-4EF8-4D6A-BCCE-749E8513BA82", "11116FB0-3E49-473A-B79F-A77D0A5A1526"); + + var people = _sut.CreateSet(table); + + people.First().GuidId.Should().Be(new Guid("8A6F6A2F-4EF8-4D6A-BCCE-749E8513BA82")); + people.First().NullableGuidId.Should().Be(new Guid("11116FB0-3E49-473A-B79F-A77D0A5A1526")); + } + + [Fact] + public void Sets_uints_on_the_instance_when_the_type_is_uint() + { + var table = new Table("UnsignedInt", "NullableUnsignedInt"); + table.AddRow("1,234", "2452"); + + var people = _sut.CreateSet(table); + + people.First().UnsignedInt.Should().Be(1234); + people.First().NullableUnsignedInt.Should().Be((uint?)2452); + } + + [Fact] + public void Sets_chars_on_the_instance_when_the_type_is_char() + { + var table = new Table("MiddleInitial", "NullableChar"); + table.AddRow("O", "K"); + + var people = _sut.CreateSet(table); + + people.First().MiddleInitial.Should().Be('O'); + people.First().NullableChar.Should().Be('K'); + } + + [Fact] + public void Works_with_valueTuples() + { + var table = new Table("Name", "Age", "HiScore", "ShoeSize"); + table.AddRow("Rich", "48", "345467", "9.5"); + table.AddRow("Sarah", "45", "12654", "4.0"); + + var people = _sut.CreateSet<(string Name, int Age, int HiScore, decimal ShoeSize)>(table); + + people.Should() + .BeEquivalentTo( + new (string Name, int Age, int HiScore, decimal ShoeSize)[] + { + ("Rich", 48, 345467, 9.5m), + ("Sarah", 45, 12654, 4.0m) + }); + } + } +} diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/ValueRetrieverTests/ArrayRetrieverTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/ValueRetrieverTests/ArrayRetrieverTests.cs index 7fd1b736d..a556263b7 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/ValueRetrieverTests/ArrayRetrieverTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/ValueRetrieverTests/ArrayRetrieverTests.cs @@ -1,14 +1,15 @@ using System; using System.Collections.Generic; +using Reqnroll.Assist; using Reqnroll.Assist.ValueRetrievers; namespace Reqnroll.RuntimeTests.AssistTests.ValueRetrieverTests { public class ArrayRetrieverTests : EnumerableRetrieverTests { - protected override EnumerableValueRetriever CreateTestee() + protected override EnumerableValueRetriever CreateTestee(Service service) { - return new ArrayValueRetriever(); + return new ArrayValueRetriever(service); } protected override IEnumerable BuildPropertyTypes(Type valueType) @@ -16,4 +17,4 @@ protected override IEnumerable BuildPropertyTypes(Type valueType) yield return valueType.MakeArrayType(); } } -} \ No newline at end of file +} diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/ValueRetrieverTests/EnumerableRetrieverTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/ValueRetrieverTests/EnumerableRetrieverTests.cs index 4c7db754a..d85b48572 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/ValueRetrieverTests/EnumerableRetrieverTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/ValueRetrieverTests/EnumerableRetrieverTests.cs @@ -6,6 +6,7 @@ using System.Threading; using FluentAssertions; using FluentAssertions.Common; +using Reqnroll.Assist; using Reqnroll.Assist.ValueRetrievers; using Xunit; @@ -74,9 +75,10 @@ protected EnumerableRetrieverTests() [MemberData(nameof(CanRetrieveData))] public void Can_retrieve_value_enumeration_properties(Type valueType) { + var service = new Service(); foreach (var propertyType in BuildPropertyTypes(valueType)) { - var retriever = CreateTestee(); + var retriever = CreateTestee(service); var actual = retriever.CanRetrieve(new KeyValuePair(), null, propertyType); @@ -106,9 +108,10 @@ public void Trims_the_individual_values(Type valueType, string[] textValues, IEn private void TestRetrieve(Type valueType, string fieldValue, IEnumerable expectedValues) { + var service = new Service(); foreach (var propertyType in BuildPropertyTypes(valueType)) { - var retriever = CreateTestee(); + var retriever = CreateTestee(service); var resultObject = retriever.Retrieve(new KeyValuePair(FieldName, fieldValue), null, propertyType); @@ -117,7 +120,7 @@ private void TestRetrieve(Type valueType, string fieldValue, IEnumerable expecte } } - protected abstract EnumerableValueRetriever CreateTestee(); + protected abstract EnumerableValueRetriever CreateTestee(Service service); protected abstract IEnumerable BuildPropertyTypes(Type valueType); } diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/ValueRetrieverTests/ListRetrieverTests.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/ValueRetrieverTests/ListRetrieverTests.cs index 4e1086b3c..a37eb59e3 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/ValueRetrieverTests/ListRetrieverTests.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/ValueRetrieverTests/ListRetrieverTests.cs @@ -1,15 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; +using Reqnroll.Assist; using Reqnroll.Assist.ValueRetrievers; namespace Reqnroll.RuntimeTests.AssistTests.ValueRetrieverTests { public class ListRetrieverTests : EnumerableRetrieverTests { - protected override EnumerableValueRetriever CreateTestee() + protected override EnumerableValueRetriever CreateTestee(Service service) { - return new ListValueRetriever(); + return new ListValueRetriever(service); } protected override IEnumerable BuildPropertyTypes(Type valueType) diff --git a/Tests/Reqnroll.RuntimeTests/AssistTests/WorkingExampleOfValueRetrieverAndComparerAddition.cs b/Tests/Reqnroll.RuntimeTests/AssistTests/WorkingExampleOfValueRetrieverAndComparerAddition.cs index 526784aa7..263485bde 100644 --- a/Tests/Reqnroll.RuntimeTests/AssistTests/WorkingExampleOfValueRetrieverAndComparerAddition.cs +++ b/Tests/Reqnroll.RuntimeTests/AssistTests/WorkingExampleOfValueRetrieverAndComparerAddition.cs @@ -9,15 +9,15 @@ namespace Reqnroll.RuntimeTests.AssistTests { - public class FancyName { public string FirstName { get; set; } + public string LastName; public override string ToString() { - return String.Join(" ", new string[]{ FirstName, LastName }); + return String.Join(" ", new string[] { FirstName, LastName }); } } @@ -28,17 +28,16 @@ public class FancyLad public class FancyNameValueRetriever : IValueRetriever { - public static FancyName Parse(string fullName) { var firstName = fullName.ToString().Split(' ').First(); - var lastName = fullName.ToString().Split(' ').Last(); + var lastName = fullName.ToString().Split(' ').Last(); return new FancyName() { FirstName = firstName, LastName = lastName }; } public IEnumerable TypesForWhichIRetrieveValues() { - return new Type[]{ typeof(FancyName) }; + return new Type[] { typeof(FancyName) }; } public object Retrieve(KeyValuePair keyValuePair, Type targetType, Type propertyType) @@ -50,7 +49,6 @@ public bool CanRetrieve(KeyValuePair keyValuePair, Type targetTy { return TypesForWhichIRetrieveValues().Contains(type); } - } public class FancyNameValueComparer : IValueComparer @@ -63,19 +61,17 @@ public bool CanCompare(object actualValue) public bool Compare(string expectedValue, object actualValue) { var expected = FancyNameValueRetriever.Parse(expectedValue); - var actual = (FancyName)actualValue; + var actual = (FancyName)actualValue; return expected.FirstName == actual.FirstName && expected.LastName == actual.LastName; } } - + [Obsolete] public class WorkingExampleOfValueRetrieverAndComparerAddition : IDisposable { - [Fact] public void Should_be_able_to_retrieve_the_fancy_name() { - Service.Instance.ValueRetrievers.Register(new FancyNameValueRetriever()); var table = new Table("Field", "Value"); @@ -97,7 +93,7 @@ public void Should_be_able_to_compare_the_fancy_name() table.AddRow("Name", "John Galt"); var expectedName = new FancyName() { FirstName = "John", LastName = "Galt" }; - var expectedLad = new FancyLad() { Name = expectedName }; + var expectedLad = new FancyLad() { Name = expectedName }; table.CompareToInstance(expectedLad); } @@ -108,12 +104,12 @@ public void Dispose() } } - /***************************************************/ public class Product { public string Name { get; set; } + public ProductCategory Category { get; set; } } @@ -129,7 +125,6 @@ public override string ToString() public class ProductCategoryValueRetriever : IValueRetriever { - public static ProductCategory Parse(string name) { return new ProductCategory() { Name = name }; @@ -137,7 +132,7 @@ public static ProductCategory Parse(string name) public IEnumerable TypesForWhichIRetrieveValues() { - return new Type[]{ typeof(ProductCategory) }; + return new Type[] { typeof(ProductCategory) }; } public object Retrieve(KeyValuePair keyValuePair, Type targetType, Type propertyType) @@ -149,7 +144,6 @@ public bool CanRetrieve(KeyValuePair keyValuePair, Type targetTy { return TypesForWhichIRetrieveValues().Contains(type); } - } public class ProductCategoryValueComparer : IValueComparer @@ -162,18 +156,17 @@ public bool CanCompare(object actualValue) public bool Compare(string expectedValue, object actualValue) { var expected = ProductCategoryValueRetriever.Parse(expectedValue); - var actual = (ProductCategory)actualValue; + var actual = (ProductCategory)actualValue; return expected.Name == actual.Name; } } - + [Obsolete] public class AnotherWorkingExampleOfValueRetrieverAndComparerAddition : IDisposable { [Fact] public void Should_be_able_to_retrieve_the_category() { - Service.Instance.ValueRetrievers.Register(new ProductCategoryValueRetriever()); var table = new Table("Field", "Value"); @@ -205,7 +198,6 @@ public void Should_be_able_to_compare_the_category() public void Dispose() { Service.Instance.RestoreDefaults(); - } } } diff --git a/Tests/Reqnroll.Specs/StepDefinitions/ExecutionResultSteps.cs b/Tests/Reqnroll.Specs/StepDefinitions/ExecutionResultSteps.cs index 9c0ee1b43..0a5c156ba 100644 --- a/Tests/Reqnroll.Specs/StepDefinitions/ExecutionResultSteps.cs +++ b/Tests/Reqnroll.Specs/StepDefinitions/ExecutionResultSteps.cs @@ -1,12 +1,10 @@ using System; using System.IO; using System.Linq; -using System.Text.RegularExpressions; using FluentAssertions; using Reqnroll.Assist; using Reqnroll.TestProjectGenerator; using Reqnroll.TestProjectGenerator.Driver; -using Reqnroll.TestProjectGenerator.Helpers; namespace Reqnroll.Specs.StepDefinitions { @@ -17,13 +15,15 @@ public class ExecutionResultSteps private readonly VSTestExecutionDriver _vsTestExecutionDriver; private readonly TestProjectFolders _testProjectFolders; private readonly TestRunLogDriver _testRunLogDriver; + private readonly TableHelpers _tableHelpers; - public ExecutionResultSteps(BindingsDriver bindingsDriver, VSTestExecutionDriver vsTestExecutionDriver, TestProjectFolders testProjectFolders, TestRunLogDriver testRunLogDriver) + public ExecutionResultSteps(BindingsDriver bindingsDriver, VSTestExecutionDriver vsTestExecutionDriver, TestProjectFolders testProjectFolders, TestRunLogDriver testRunLogDriver, TableHelpers tableHelpers) { _bindingsDriver = bindingsDriver; _vsTestExecutionDriver = vsTestExecutionDriver; _testProjectFolders = testProjectFolders; _testRunLogDriver = testRunLogDriver; + _tableHelpers = tableHelpers; } [Then(@"the tests were executed successfully")] @@ -39,14 +39,14 @@ public void ThenAllTestsShouldPass() public void ThenTheExecutionSummaryShouldContain(Table expectedTestExecutionResult) { _vsTestExecutionDriver.LastTestExecutionResult.Should().NotBeNull(); - expectedTestExecutionResult.CompareToInstance(_vsTestExecutionDriver.LastTestExecutionResult); + _tableHelpers.CompareToInstance(expectedTestExecutionResult,_vsTestExecutionDriver.LastTestExecutionResult); // if we only assert for total number of tests, we will make an additional assertion for the // successful tests with the same count, to highlight hidden runtime errors if (expectedTestExecutionResult.Header.Count == 1 && expectedTestExecutionResult.ContainsColumn("Total")) { expectedTestExecutionResult.RenameColumn("Total", "Succeeded"); - expectedTestExecutionResult.CompareToInstance(_vsTestExecutionDriver.LastTestExecutionResult); + _tableHelpers.CompareToInstance(expectedTestExecutionResult,_vsTestExecutionDriver.LastTestExecutionResult); } } diff --git a/Tests/Reqnroll.Specs/StepDefinitions/GherkinParserSteps.cs b/Tests/Reqnroll.Specs/StepDefinitions/GherkinParserSteps.cs index dd6be8aae..7a9c292a7 100644 --- a/Tests/Reqnroll.Specs/StepDefinitions/GherkinParserSteps.cs +++ b/Tests/Reqnroll.Specs/StepDefinitions/GherkinParserSteps.cs @@ -10,10 +10,12 @@ namespace Reqnroll.Specs.StepDefinitions public class GherkinParserSteps { private readonly ParserDriver _parserDriver; - - public GherkinParserSteps(ParserDriver parserDriver) + private readonly TableHelpers _tableHelpers; + + public GherkinParserSteps(ParserDriver parserDriver, TableHelpers tableHelpers) { _parserDriver = parserDriver; + _tableHelpers = tableHelpers; } [Given(@"there is a Gherkin file as")] @@ -37,7 +39,7 @@ public void ThenNoParsingErrorIsReported() [StepArgumentTransformation] public List ConvertExpectedErrors(Table table) { - return table.CreateSet().ToList(); + return _tableHelpers.CreateSet(table).ToList(); } [Then(@"the following errors are provided")]