I'm looking for the elegant expression to test if an enumerable contains a 'subset' of itself.
Lets me illustrate with a sample:
[Fact]
public void Test1()
{
// Arrange
var expected = new[]
{
new {F1 = 1, F2 = "1" },
new {F1 = 2, F2 = "2" },
};
// Act
var actual = new[]
{
new {F1 = 1, F2 = "1", F3 = true },
new {F1 = 2, F2 = "2", F3 = true },
new {F1 = 3, F2 = "3", F3 = true },
};
// Assert
actual
.Should()
.LookingForFluentAssertionsExpression( //<-- I'm looking for this part
expected,
options => options.SomeOptions(),
because: "expected is a 'subset' of actual"
);
}
I have tried unsuccessfully with Object graph comparison:
// Assert
actual
.Should()
.BeEquivalentTo(expected, o => o.ExcludingMissingMembers());
Expected actual to be a collection with 2 item(s), but {{ F1 = 1, F2 = 1, F3 = True }, { F1 = 2, F2 = 2, F3 = True }, { F1 = 3, F2 = 3, F3 = True }}"
"contains 1 item(s) more than"
"{{ F1 = 1, F2 = 1 }, { F1 = 2, F2 = 2 }}.
Obviously, I can do:
// Assert
actual
.Where(a => expected.Any(e=>e.F1 == a.F1 && e.F2 == a.F2))
.Should()
.BeEquivalentTo(expected, o => o.ExcludingMissingMembers());
but looks a bit dirty.
Another option is:
// Assert
expected
.ToList()
.ForEach(expectedItem =>
actual
.Should()
.ContainEquivalentOf(
expectation: expectedItem,
config: o => o.ExcludingMissingMembers())
);
// Or the same without Linq:
//
//foreach (var expectedItem in expected)
//{
// actual
// .Should()
// .ContainEquivalentOf(
// expectation: expectedItem,
// config: o => o.ExcludingMissingMembers());
//}
but is not readable at all.
CodePudding user response:
You can use two calls of ContainEquivalentOf
where you pass an item from the expected
collection.
CodePudding user response:
The HashSet<T>
has the methods .IsSuperset() and .IsSubset() to make the desired checks:
// Arrange
var expected = new[]
{
new { F1 = 1, F2 = "1", F3 = true },
new { F1 = 2, F2 = "2", F3 = true },
};
// Act
var actual = new[]
{
new { F1 = 1, F2 = "1", F3 = true },
new { F1 = 2, F2 = "2", F3 = true },
new { F1 = 3, F2 = "3", F3 = true },
};
// Assert
var actualHashSet = actual.ToHashSet();
var isSuperset = actualHashSet.IsSupersetOf(expected);
isSuperset.ShouldBeTrue();
var expectedHashSet = expected.ToHashSet();
var isSubset = expectedHashSet.IsSubsetOf(actual);
isSubset.ShouldBeTrue();
CodePudding user response:
At the end, I coded it using a ClassData. I don't know if this is the best solution, I post it here with the other answers. Feel free to criticize this answer. We are here to learn.
public class CalculatorTestData : IEnumerable<object[]>
{
public IEnumerator<object[]> GetEnumerator()
{
yield return new object[] { new { F1 = 1, F2 = "1" }, "reason 1" };
yield return new object[] { new { F1 = 2, F2 = "2" }, "reason 2" };
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
[Theory]
[ClassData(typeof(CalculatorTestData))]
public void Test2(object expected, string because)
{
// Arrange
// Act
var actual = new[]
{
new {F1 = 1, F2 = "1", F3 = true },
new {F1 = 2, F2 = "2", F3 = true },
new {F1 = 3, F2 = "3", F3 = true },
};
// Assert
actual
.Should()
.ContainEquivalentOf(
expectation: expected,
config: o => o.ExcludingMissingMembers(),
because: because);
}