CollectionEquivalent Constraint
CollectionEquivalentConstraint tests that two IEnumerables are equivalent - that they contain the same items, in any
order. Two collections are equivalent if they have the same number of elements and every element in one collection has a
matching element in the other.
Usage
Is.EquivalentTo(IEnumerable expected)
Is.Not.EquivalentTo(IEnumerable expected)
Modifiers
.IgnoreCase
.IgnoreWhiteSpace // From version 4.2
.Using(IEqualityComparer comparer)
.Using(IComparer comparer)
.Using<T>(IEqualityComparer<T> comparer)
.Using<T>(IComparer<T> comparer)
.Using<T>(Comparison<T> comparer)
.Using<T>(Func<T, T, bool> comparer)
.UsingPropertiesComparer() // From version 4.1
Examples
private sealed class Person(string name, int age)
{
public string Name { get; } = name;
public int Age { get; } = age;
}
[Test]
public void CollectionEquivalentConstraint_Examples()
{
int[] expected = { 1, 2, 3 };
int[] actual = { 3, 2, 1 };
// Order doesn't matter
Assert.That(actual, Is.EquivalentTo(expected));
// Different collections with same elements
Assert.That(new List<int> { 1, 2, 3 }, Is.EquivalentTo(new[] { 3, 1, 2 }));
// Duplicates matter
Assert.That(new[] { 1, 1, 2 }, Is.Not.EquivalentTo(new[] { 1, 2, 2 }));
Assert.That(new[] { 1, 1, 2 }, Is.EquivalentTo(new[] { 2, 1, 1 }));
// Case-insensitive for strings
Assert.That(new[] { "A", "B" }, Is.EquivalentTo(new[] { "b", "a" }).IgnoreCase);
// Compare objects without value equality property by property
Person[] expectedPeople = [new("Alice", 30), new("Bob", 25)];
Person[] actualPeople = [new("Bob", 25), new("Alice", 30)];
Assert.That(actualPeople, Is.EquivalentTo(expectedPeople).UsingPropertiesComparer());
}
Notes
- To compare items in a specific order, use
Is.EqualTo()instead. - Duplicate items matter:
{1, 2, 2}is not equivalent to{1, 2, 3}even though they have the same length. - The constraint checks that each item in one collection has exactly one matching item in the other, accounting for duplicates correctly.
- There is no
Withinmodifier. Equivalence matches items by grouping equal values, which requires equality to be transitive, and a tolerance is not. A tolerant comparer passed toUsingis accepted but can give results that depend on the order of the items. To compare approximate values regardless of order, sort both collections and useIs.EqualTo(...).Within(...), or check each expected value withHas.Exactly(1).EqualTo(...).Within(...). See Tolerances.
See Also
- Equal Constraint - For ordered comparison
- Tolerances - Approximate comparisons of unordered collections
- CollectionSubset Constraint
- CollectionSuperset Constraint
- AllItems Constraint