Skip to content

Commit

Permalink
Added base type NonGenericCollectionWrapperBase in FluentAssertions/D…
Browse files Browse the repository at this point in the history
…ata/Wrappers and three subclasses DataTableCollectionWrapper, DataRowCollectionWrapper and DataColumnCollectionWrapper. These ensure that the Count property is passed through to the underlying implementation, and also allow code that knows about them to directly access the wrapped collection object.

Updated AssertionExtensions.c to use DataTableCollectionWrapper, DataColumnCollectionWrapper and DataRowCollectionWrapper instead of System.Linq's .Cast<TItem> to produce generic collections for use with GenericCollectionAssertions<TItem> in Should overloads for DataTableCollection, DataColumnCollection and DataRowCollection.
Updated DataTableCollectionAssertionExtensions.cs and DataColumnCollectionAssertionExtensions.cs to check if the assertion subject is a DataTableCollectionWrapper or DataColumnCollectionWrapper, respectively, so that existence of the member can be tested with the underlying Contains functionality rather than requiring the collection to be enumerated.
  • Loading branch information
logiclrd committed Feb 18, 2022
1 parent f579d96 commit 68c839e
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 7 deletions.
7 changes: 4 additions & 3 deletions Src/FluentAssertions/AssertionExtensions.cs
Expand Up @@ -13,6 +13,7 @@
using FluentAssertions.Collections;
using FluentAssertions.Common;
using FluentAssertions.Data;
using FluentAssertions.Data.Wrappers;
#if !NETSTANDARD2_0
using FluentAssertions.Events;
#endif
Expand Down Expand Up @@ -391,7 +392,7 @@ public static StringCollectionAssertions Should(this IEnumerable<string> @this)
[Pure]
public static GenericCollectionAssertions<DataTable> Should(this DataTableCollection actualValue)
{
return new GenericCollectionAssertions<DataTable>(actualValue.Cast<DataTable>());
return new GenericCollectionAssertions<DataTable>(new DataTableCollectionWrapper(actualValue));
}

/// <summary>
Expand All @@ -400,7 +401,7 @@ public static GenericCollectionAssertions<DataTable> Should(this DataTableCollec
[Pure]
public static GenericCollectionAssertions<DataColumn> Should(this DataColumnCollection actualValue)
{
return new GenericCollectionAssertions<DataColumn>(actualValue.Cast<DataColumn>());
return new GenericCollectionAssertions<DataColumn>(new DataColumnCollectionWrapper(actualValue));
}

/// <summary>
Expand All @@ -409,7 +410,7 @@ public static GenericCollectionAssertions<DataColumn> Should(this DataColumnColl
[Pure]
public static GenericCollectionAssertions<DataRow> Should(this DataRowCollection actualValue)
{
return new GenericCollectionAssertions<DataRow>(actualValue.Cast<DataRow>());
return new GenericCollectionAssertions<DataRow>(new DataRowCollectionWrapper (actualValue));
}

/// <summary>
Expand Down
Expand Up @@ -3,6 +3,7 @@

using FluentAssertions.Collections;
using FluentAssertions.Common;
using FluentAssertions.Data.Wrappers;
using FluentAssertions.Execution;

namespace FluentAssertions
Expand Down Expand Up @@ -114,7 +115,18 @@ public static class DataColumnCollectionAssertionExtensions
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)
Expand Down Expand Up @@ -150,7 +162,18 @@ public static class DataColumnCollectionAssertionExtensions
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)
Expand Down
Expand Up @@ -3,6 +3,7 @@

using FluentAssertions.Collections;
using FluentAssertions.Common;
using FluentAssertions.Data.Wrappers;
using FluentAssertions.Execution;

namespace FluentAssertions
Expand Down Expand Up @@ -101,7 +102,18 @@ public static class DataTableCollectionAssertionExtensions
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)
Expand Down Expand Up @@ -137,7 +149,18 @@ public static class DataTableCollectionAssertionExtensions
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)
Expand Down
16 changes: 16 additions & 0 deletions Src/FluentAssertions/Data/Wrappers/DataColumnCollectionWrapper.cs
@@ -0,0 +1,16 @@
using System.Data;

namespace FluentAssertions.Data.Wrappers
{
internal class DataColumnCollectionWrapper : NonGenericCollectionWrapperBase<DataColumnCollection, DataColumn>
{
public DataColumnCollectionWrapper(DataColumnCollection collection)
: base(collection)
{
}

public override int Count => UnderlyingCollection.Count;

public bool Contains(string columnName) => UnderlyingCollection.Contains(columnName);
}
}
14 changes: 14 additions & 0 deletions Src/FluentAssertions/Data/Wrappers/DataRowCollectionWrapper.cs
@@ -0,0 +1,14 @@
using System.Data;

namespace FluentAssertions.Data.Wrappers
{
internal class DataRowCollectionWrapper : NonGenericCollectionWrapperBase<DataRowCollection, DataRow>
{
public DataRowCollectionWrapper(DataRowCollection collection)
: base(collection)
{
}

public override int Count => UnderlyingCollection.Count;
}
}
16 changes: 16 additions & 0 deletions Src/FluentAssertions/Data/Wrappers/DataTableCollectionWrapper.cs
@@ -0,0 +1,16 @@
using System.Data;

namespace FluentAssertions.Data.Wrappers
{
internal class DataTableCollectionWrapper : NonGenericCollectionWrapperBase<DataTableCollection, DataTable>
{
public DataTableCollectionWrapper(DataTableCollection collection)
: base(collection)
{
}

public override int Count => UnderlyingCollection.Count;

public bool Contains(string tableName) => UnderlyingCollection.Contains(tableName);
}
}
@@ -0,0 +1,41 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace FluentAssertions.Data.Wrappers
{
internal abstract class NonGenericCollectionWrapperBase<TCollection, TItem> : ICollection<TItem>, IEnumerable<TItem>
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<TItem> GetEnumerator() => UnderlyingCollection.Cast<TItem>().GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => UnderlyingCollection.GetEnumerator();

public virtual bool Contains(TItem item) => UnderlyingCollection.Cast<TItem>().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<T>:
// * 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();
}
}

0 comments on commit 68c839e

Please sign in to comment.