diff --git a/TUnit.Assertions.Tests/Bugs/Tests3489.cs b/TUnit.Assertions.Tests/Bugs/Tests3489.cs new file mode 100644 index 0000000000..ce9e2b90d3 --- /dev/null +++ b/TUnit.Assertions.Tests/Bugs/Tests3489.cs @@ -0,0 +1,86 @@ +namespace TUnit.Assertions.Tests.Bugs; + +/// +/// Tests for issue #3489: IsEquivalentTo does not work properly with nested collections in records +/// +public class Tests3489 +{ + [Test] + public async Task IsEquivalentTo_WithNestedCollections_InRecords_ShouldSucceed() + { + // Arrange - Create identical hierarchical structures + var actual = new List + { + new() + { + Name = "Parent1", + Children = + [ + new Person { Name = "Child1", Children = [] }, + new Person { Name = "Child2", Children = [] } + ] + }, + new() + { + Name = "Parent2", + Children = [new Person { Name = "Child3", Children = [] }] + } + }; + + var expected = new List + { + new() + { + Name = "Parent1", + Children = + [ + new Person { Name = "Child1", Children = [] }, + new Person { Name = "Child2", Children = [] } + ] + }, + new() + { + Name = "Parent2", + Children = [new Person { Name = "Child3", Children = [] }] + } + }; + + // Act & Assert - Should recognize structural equivalence despite different List instances + await Assert.That(actual).IsEquivalentTo(expected); + } + + [Test] + public async Task IsEquivalentTo_WithNestedCollections_InRecords_DifferentData_ShouldFail() + { + // Arrange + var actual = new List + { + new() + { + Name = "Parent1", + Children = [new Person { Name = "Child1", Children = [] }] + } + }; + + var expected = new List + { + new() + { + Name = "Parent1", + Children = [new Person { Name = "DifferentChild", Children = [] }] + } + }; + + // Act & Assert - Should fail when actual data is different + var exception = await Assert.ThrowsAsync( + async () => await Assert.That(actual).IsEquivalentTo(expected)); + + await Assert.That(exception).IsNotNull(); + } + + private sealed record Person + { + public required string Name { get; init; } + public required List Children { get; init; } + } +} diff --git a/TUnit.Assertions/Conditions/Helpers/StructuralEqualityComparer.cs b/TUnit.Assertions/Conditions/Helpers/StructuralEqualityComparer.cs index 9a723cd5de..1c0a7448da 100644 --- a/TUnit.Assertions/Conditions/Helpers/StructuralEqualityComparer.cs +++ b/TUnit.Assertions/Conditions/Helpers/StructuralEqualityComparer.cs @@ -41,11 +41,6 @@ public bool Equals(T? x, T? y) return EqualityComparer.Default.Equals(x, y); } - if (typeof(IEquatable).IsAssignableFrom(type)) - { - return ((IEquatable)x).Equals(y); - } - return CompareStructurally(x, y, new HashSet(new ReferenceEqualityComparer())); }