Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve coverage on data assertions #2037

Merged
merged 3 commits into from Nov 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 1 addition & 44 deletions Src/FluentAssertions/Data/DataEquivalencyAssertionOptions.cs
@@ -1,5 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq.Expressions;
Expand Down Expand Up @@ -32,51 +31,9 @@ internal class DataEquivalencyAssertionOptions<T> : EquivalencyAssertionOptions<

public ISet<string> ExcludeColumnNames => excludeColumnNames;

public IReadOnlyDictionary<string, ISet<string>> ExcludeColumnNamesByTableName { get; }

private class ColumnNamesByTableNameAdapter : IReadOnlyDictionary<string, ISet<string>>
{
private readonly DataEquivalencyAssertionOptions<T> owner;

public ColumnNamesByTableNameAdapter(DataEquivalencyAssertionOptions<T> owner)
{
this.owner = owner;
}

public ISet<string> this[string key] => owner.excludeColumnNamesByTableName[key];

public IEnumerable<string> Keys => owner.excludeColumnNamesByTableName.Keys;

public IEnumerable<ISet<string>> Values => owner.excludeColumnNamesByTableName.Values;

public int Count => owner.excludeColumnNamesByTableName.Count;

public bool ContainsKey(string key) => owner.excludeColumnNamesByTableName.ContainsKey(key);

public bool TryGetValue(string key, out ISet<string> value)
{
bool result = owner.excludeColumnNamesByTableName.TryGetValue(key, out HashSet<string> concreteValue);

value = concreteValue;

return result;
}

public IEnumerator<KeyValuePair<string, ISet<string>>> GetEnumerator()
{
foreach (KeyValuePair<string, HashSet<string>> entry in owner.excludeColumnNamesByTableName)
{
yield return new KeyValuePair<string, ISet<string>>(entry.Key, entry.Value);
}
}

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

public DataEquivalencyAssertionOptions(EquivalencyAssertionOptions defaults)
: base(defaults)
{
ExcludeColumnNamesByTableName = new ColumnNamesByTableNameAdapter(this);
}

public IDataEquivalencyAssertionOptions<T> AllowingMismatchedTypes()
Expand Down Expand Up @@ -186,7 +143,7 @@ private static MemberInfo GetMemberAccessTargetMember(Expression expression)
return memberExpression.Member;
}

throw new Exception("Expression must be a simple member access");
throw new ArgumentException("Expression must be a simple member access", nameof(expression));
}

private static Expression<Func<IMemberInfo, bool>> BuildMemberSelectionPredicate(Type relatedSubjectType, MemberInfo referencedMember)
Expand Down
38 changes: 38 additions & 0 deletions Tests/FluentAssertions.Equivalency.Specs/DataColumnSpecs.cs
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Data;
using Xunit;
using Xunit.Sdk;
Expand Down Expand Up @@ -77,6 +78,43 @@ public void When_DataColumn_has_changes_but_is_excluded_it_should_succeed()
.ExcludingColumn(dataColumn2));
}

[Fact]
public void When_DataColumn_has_changes_but_is_excluded_as_params_it_should_succeed()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🌱 We really need to start improving those test names, but that's besides the point of this PR.

{
// Arrange
var dataSet1 = CreateDummyDataSet<TypedDataSetSubclass>();
var dataSet2 = new TypedDataSetSubclass(dataSet1);

var dataColumn1 = dataSet1.TypedDataTable1.DecimalColumn;
var dataColumn2 = dataSet2.TypedDataTable1.DecimalColumn;

dataColumn2.Unique = true;
dataColumn2.Caption = "Test";

// Act & Assert
dataColumn1.Should().BeEquivalentTo(dataColumn2, options => options
.ExcludingColumns(dataColumn2));
}

[Fact]
public void When_DataColumn_has_changes_but_is_excluded_as_enumerable_it_should_succeed()
{
// Arrange
var dataSet1 = CreateDummyDataSet<TypedDataSetSubclass>();
var dataSet2 = new TypedDataSetSubclass(dataSet1);

var dataColumn1 = dataSet1.TypedDataTable1.DecimalColumn;
var dataColumn2 = dataSet2.TypedDataTable1.DecimalColumn;

dataColumn2.Unique = true;
dataColumn2.Caption = "Test";

// Act & Assert
IEnumerable<DataColumn> excludedColumns = new[] { dataColumn2 };
dataColumn1.Should().BeEquivalentTo(dataColumn2, options => options
.ExcludingColumns(excludedColumns));
}

[Fact]
public void When_DataColumn_has_changes_but_is_excluded_it_should_succeed_when_compared_via_DataTable()
{
Expand Down
34 changes: 33 additions & 1 deletion Tests/FluentAssertions.Equivalency.Specs/TypedDataSetSpecs.cs
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
Expand Down Expand Up @@ -188,7 +189,7 @@ public void When_HasErrors_does_not_match_and_property_is_not_excluded_it_should
dataSet2.TypedDataTable1.Rows[0].RowError = "Manually added error";

// Act
Action action = () => dataSet1.Should().BeEquivalentTo(dataSet2, config => config.ExcludingTables("TypedDataTable1"));
Action action = () => dataSet1.Should().BeEquivalentTo(dataSet2, config => config.ExcludingTable("TypedDataTable1"));

// Assert
action.Should().Throw<XunitException>().Which.Message.Should().Contain("HasErrors");
Expand All @@ -204,11 +205,42 @@ public void When_HasErrors_does_not_match_and_property_is_excluded_it_should_suc

dataSet2.TypedDataTable1.Rows[0].RowError = "Manually added error";

// Act & Assert
dataSet1.Should().BeEquivalentTo(dataSet2,
config => config.Excluding(dataSet => dataSet.HasErrors).ExcludingTable("TypedDataTable1"));
}

[Fact]
public void When_HasErrors_does_not_match_and_property_is_excluded_as_params_it_should_succeed()
{
// Arrange
var dataSet1 = CreateDummyDataSet<TypedDataSetSubclass>();

var dataSet2 = new TypedDataSetSubclass(dataSet1);

dataSet2.TypedDataTable1.Rows[0].RowError = "Manually added error";

// Act & Assert
dataSet1.Should().BeEquivalentTo(dataSet2,
config => config.Excluding(dataSet => dataSet.HasErrors).ExcludingTables("TypedDataTable1"));
}

[Fact]
public void When_HasErrors_does_not_match_and_property_is_excluded_as_list_it_should_succeed()
{
// Arrange
var dataSet1 = CreateDummyDataSet<TypedDataSetSubclass>();

var dataSet2 = new TypedDataSetSubclass(dataSet1);

dataSet2.TypedDataTable1.Rows[0].RowError = "Manually added error";

// Act & Assert
IEnumerable<string> excludedTales = new[] { "TypedDataTable1" };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excludedTales -> excludedTables

dataSet1.Should().BeEquivalentTo(dataSet2,
config => config.Excluding(dataSet => dataSet.HasErrors).ExcludingTables(excludedTales));
}

[Fact]
public void When_Locale_does_not_match_and_property_is_not_excluded_it_should_fail()
{
Expand Down