Skip to content

Commit

Permalink
The expectation node identified as a cyclic reference is still compar…
Browse files Browse the repository at this point in the history
…ed to the subject node using simple equality.
  • Loading branch information
dennisdoomen committed Nov 11, 2024
1 parent d4acc9d commit ca7c8f6
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.507">
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
19 changes: 18 additions & 1 deletion Src/FluentAssertions/Equivalency/EquivalencyValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ public void RecursivelyAssertEquality(Comparands comparands, IEquivalencyValidat
{
TrackWhatIsNeededToProvideContextToFailures(scope, comparands, context.CurrentNode);

if (!context.IsCyclicReference(comparands.Expectation))
if (context.IsCyclicReference(comparands.Expectation))
{
AssertComparandsPointToActualObjects(comparands);
}
else
{
TryToProveNodesAreEquivalent(comparands, context);
}
Expand All @@ -62,6 +66,19 @@ private static void TrackWhatIsNeededToProvideContextToFailures(AssertionScope s
scope.TrackComparands(comparands.Subject, comparands.Expectation);
}

private static void AssertComparandsPointToActualObjects(Comparands comparands)
{
if (ReferenceEquals(comparands.Subject, comparands.Expectation))
{
return;
}

if (comparands.Subject is null || comparands.Expectation is null)
{
comparands.Subject.Should().BeSameAs(comparands.Expectation);
}
}

private void TryToProveNodesAreEquivalent(Comparands comparands, IEquivalencyValidationContext context)
{
using var _ = context.Tracer.WriteBlock(node => node.Description);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using JetBrains.Annotations;
using Xunit;
using Xunit.Sdk;

Expand Down Expand Up @@ -68,6 +69,95 @@ public void By_default_cyclic_references_are_not_valid()
.WithMessage("Expected property cyclicRoot.Level.Root to be*but it contains a cyclic reference*");
}

[Fact]
public void The_cyclic_reference_itself_will_be_compared_using_simple_equality()
{
// Arrange
var expectedChild = new Child2
{
Id = 1
};

var expectedParent = new Parent2
{
Id = 100,
Children = [expectedChild]
};

expectedChild.Parent2 = expectedParent;

var actualChild = new Child2
{
Id = 1
};

var actualParent = new Parent2
{
Id = 100,
Children = [actualChild]
};

// Act
var act = () => actualParent.Should().BeEquivalentTo(expectedParent, options => options.IgnoringCyclicReferences());

// Assert
act.Should().Throw<XunitException>()
.WithMessage("Expected property actualParent.Children[0].Parent2 to refer to*but found*null*");
}

[Fact]
public void The_cyclic_reference_can_be_ignored_if_the_comparands_point_to_the_same_object()
{
// Arrange
var expectedChild = new Child2
{
Id = 1
};

var expectedParent = new Parent2
{
Id = 100,
Children = [expectedChild]
};

expectedChild.Parent2 = expectedParent;

var actualChild = new Child2
{
Id = 1
};

var actualParent = new Parent2
{
Id = 100,
Children = [actualChild]
};

// Connect this child to the same parent as the expectation child
actualChild.Parent2 = expectedParent;

// Act
actualParent.Should().BeEquivalentTo(expectedParent, options => options.IgnoringCyclicReferences());
}

private class Parent2
{
[UsedImplicitly]
public int Id { get; set; }

[UsedImplicitly]
public List<Child2> Children { get; set; }
}

private class Child2
{
[UsedImplicitly]
public int Id { get; set; }

[UsedImplicitly]
public Parent2 Parent2 { get; set; }
}

[Fact]
public void Two_graphs_with_ignored_cyclic_references_can_be_compared()
{
Expand Down Expand Up @@ -216,7 +306,7 @@ public void Can_ignore_cyclic_references_for_inequivalency_assertions()

// Act / Assert
recursiveClass1.Should().NotBeEquivalentTo(recursiveClass2,
options => options.AllowingInfiniteRecursion());
options => options.AllowingInfiniteRecursion());
}

[Fact]
Expand Down
6 changes: 6 additions & 0 deletions docs/_pages/releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ sidebar:
nav: "sidebar"
---

## 6.12.3

### Fixes

* The expectation node identified as a cyclic reference is still compared to the subject node using simple equality - [2819](https://github.com/fluentassertions/fluentassertions/pull/2819)

## 6.12.2

### Fixes
Expand Down

0 comments on commit ca7c8f6

Please sign in to comment.