diff --git a/Src/FluentAssertions/AssertionExtensions.cs b/Src/FluentAssertions/AssertionExtensions.cs index 9b80852e53..082cb8d2ce 100644 --- a/Src/FluentAssertions/AssertionExtensions.cs +++ b/Src/FluentAssertions/AssertionExtensions.cs @@ -13,6 +13,7 @@ using FluentAssertions.Collections; using FluentAssertions.Common; using FluentAssertions.Data; +using FluentAssertions.Data.Wrappers; #if !NETSTANDARD2_0 using FluentAssertions.Events; #endif @@ -391,7 +392,7 @@ public static GenericDictionaryAssertions Should Should(this DataTableCollection actualValue) { - return new GenericCollectionAssertions(actualValue.Cast()); + return new GenericCollectionAssertions(new DataTableCollectionWrapper(actualValue)); } /// @@ -400,7 +401,7 @@ public static GenericCollectionAssertions Should(this DataTableCollec [Pure] public static GenericCollectionAssertions Should(this DataColumnCollection actualValue) { - return new GenericCollectionAssertions(actualValue.Cast()); + return new GenericCollectionAssertions(new DataColumnCollectionWrapper(actualValue)); } /// @@ -409,7 +410,7 @@ public static GenericCollectionAssertions Should(this DataColumnColl [Pure] public static GenericCollectionAssertions Should(this DataRowCollection actualValue) { - return new GenericCollectionAssertions(actualValue.Cast()); + return new GenericCollectionAssertions(new DataRowCollectionWrapper (actualValue)); } /// diff --git a/Src/FluentAssertions/Data/Extensions/DataColumnCollectionAssertionExtensions.cs b/Src/FluentAssertions/Data/Extensions/DataColumnCollectionAssertionExtensions.cs index 0431279df7..01235f5798 100644 --- a/Src/FluentAssertions/Data/Extensions/DataColumnCollectionAssertionExtensions.cs +++ b/Src/FluentAssertions/Data/Extensions/DataColumnCollectionAssertionExtensions.cs @@ -3,6 +3,7 @@ using FluentAssertions.Collections; using FluentAssertions.Common; +using FluentAssertions.Data.Wrappers; using FluentAssertions.Execution; namespace FluentAssertions @@ -114,7 +115,18 @@ public static AndConstraint> ContainColu assertion.Subject); } - if (!assertion.Subject.Any(column => column.ColumnName == expectedColumnName)) + bool containsColumn; + + if (assertion.Subject is DataColumnCollectionWrapper dataColumnCollection) + { + containsColumn = dataColumnCollection.Contains(expectedColumnName); + } + else + { + containsColumn = assertion.Subject.Any(column => column.ColumnName == expectedColumnName); + } + + if (!containsColumn) { Execute.Assertion .BecauseOf(because, becauseArgs) @@ -150,7 +162,18 @@ public static AndConstraint> NotContainC assertion.Subject); } - if (assertion.Subject.Any(column => column.ColumnName == unexpectedColumnName)) + bool containsColumn; + + if (assertion.Subject is DataColumnCollectionWrapper dataColumnCollection) + { + containsColumn = dataColumnCollection.Contains(unexpectedColumnName); + } + else + { + containsColumn = assertion.Subject.Any(column => column.ColumnName == unexpectedColumnName); + } + + if (containsColumn) { Execute.Assertion .BecauseOf(because, becauseArgs) diff --git a/Src/FluentAssertions/Data/Extensions/DataTableCollectionAssertionExtensions.cs b/Src/FluentAssertions/Data/Extensions/DataTableCollectionAssertionExtensions.cs index 8e2e404be5..88b072785b 100644 --- a/Src/FluentAssertions/Data/Extensions/DataTableCollectionAssertionExtensions.cs +++ b/Src/FluentAssertions/Data/Extensions/DataTableCollectionAssertionExtensions.cs @@ -3,6 +3,7 @@ using FluentAssertions.Collections; using FluentAssertions.Common; +using FluentAssertions.Data.Wrappers; using FluentAssertions.Execution; namespace FluentAssertions @@ -101,7 +102,18 @@ public static AndConstraint> ContainTable assertion.Subject); } - if (!assertion.Subject.Any(table => table.TableName == expectedTableName)) + bool containsTable; + + if (assertion.Subject is DataTableCollectionWrapper dataTableCollection) + { + containsTable = dataTableCollection.Contains(expectedTableName); + } + else + { + containsTable = assertion.Subject.Any(table => table.TableName == expectedTableName); + } + + if (!containsTable) { Execute.Assertion .BecauseOf(because, becauseArgs) @@ -137,7 +149,18 @@ public static AndConstraint> NotContainTa assertion.Subject); } - if (assertion.Subject.Any(table => table.TableName == unexpectedTableName)) + bool containsTable; + + if (assertion.Subject is DataTableCollectionWrapper dataTableCollection) + { + containsTable = dataTableCollection.Contains(unexpectedTableName); + } + else + { + containsTable = assertion.Subject.Any(table => table.TableName == unexpectedTableName); + } + + if (containsTable) { Execute.Assertion .BecauseOf(because, becauseArgs) diff --git a/Src/FluentAssertions/Data/Wrappers/DataColumnCollectionWrapper.cs b/Src/FluentAssertions/Data/Wrappers/DataColumnCollectionWrapper.cs new file mode 100644 index 0000000000..12617c0615 --- /dev/null +++ b/Src/FluentAssertions/Data/Wrappers/DataColumnCollectionWrapper.cs @@ -0,0 +1,16 @@ +using System.Data; + +namespace FluentAssertions.Data.Wrappers +{ + internal class DataColumnCollectionWrapper : NonGenericCollectionWrapperBase + { + public DataColumnCollectionWrapper(DataColumnCollection collection) + : base(collection) + { + } + + public override int Count => UnderlyingCollection.Count; + + public bool Contains(string columnName) => UnderlyingCollection.Contains(columnName); + } +} diff --git a/Src/FluentAssertions/Data/Wrappers/DataRowCollectionWrapper.cs b/Src/FluentAssertions/Data/Wrappers/DataRowCollectionWrapper.cs new file mode 100644 index 0000000000..3cd9dc8651 --- /dev/null +++ b/Src/FluentAssertions/Data/Wrappers/DataRowCollectionWrapper.cs @@ -0,0 +1,14 @@ +using System.Data; + +namespace FluentAssertions.Data.Wrappers +{ + internal class DataRowCollectionWrapper : NonGenericCollectionWrapperBase + { + public DataRowCollectionWrapper(DataRowCollection collection) + : base(collection) + { + } + + public override int Count => UnderlyingCollection.Count; + } +} diff --git a/Src/FluentAssertions/Data/Wrappers/DataTableCollectionWrapper.cs b/Src/FluentAssertions/Data/Wrappers/DataTableCollectionWrapper.cs new file mode 100644 index 0000000000..47450df51d --- /dev/null +++ b/Src/FluentAssertions/Data/Wrappers/DataTableCollectionWrapper.cs @@ -0,0 +1,16 @@ +using System.Data; + +namespace FluentAssertions.Data.Wrappers +{ + internal class DataTableCollectionWrapper : NonGenericCollectionWrapperBase + { + public DataTableCollectionWrapper(DataTableCollection collection) + : base(collection) + { + } + + public override int Count => UnderlyingCollection.Count; + + public bool Contains(string tableName) => UnderlyingCollection.Contains(tableName); + } +} diff --git a/Src/FluentAssertions/Data/Wrappers/NonGenericCollectionWrapperBase.cs b/Src/FluentAssertions/Data/Wrappers/NonGenericCollectionWrapperBase.cs new file mode 100644 index 0000000000..8f5cde5612 --- /dev/null +++ b/Src/FluentAssertions/Data/Wrappers/NonGenericCollectionWrapperBase.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace FluentAssertions.Data.Wrappers +{ + internal abstract class NonGenericCollectionWrapperBase : ICollection, IEnumerable + where TCollection : ICollection, IEnumerable + { + public TCollection UnderlyingCollection { get; private set; } + + public NonGenericCollectionWrapperBase(TCollection collection) + { + UnderlyingCollection = collection; + } + + public abstract int Count { get; } + + public bool IsReadOnly => true; + + public IEnumerator GetEnumerator() => UnderlyingCollection.Cast().GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => UnderlyingCollection.GetEnumerator(); + + public virtual bool Contains(TItem item) => UnderlyingCollection.Cast().Contains(item); + + public void CopyTo(TItem[] array, int arrayIndex) => UnderlyingCollection.CopyTo(array, arrayIndex); + + // Mutation is not supported, but these methods must be implemented to satisfy ICollection: + // * Add + // * Clear + // * Remove + + public void Add(TItem item) => throw new NotSupportedException(); + + public void Clear() => throw new NotSupportedException(); + + public bool Remove(TItem item) => throw new NotSupportedException(); + } +}