-
Notifications
You must be signed in to change notification settings - Fork 733
Description
Description
If I keep it short: having override Equals on objects I have to disable using it with ComparingByMembers. But if I do so, the IgnoreCyclicReferences seem to stop working.
Here the details.
We have written a lot of NHibernate persistence tests, where we are using FluentAssertions BeEquivalentOf.
After adding a recommended for NH Equals-override in the DomainBase class we've got multiple issues with FluentAssertions.
We had to add a Configuration option ComparingByMembers<DomainBase>() to prevent FluentAssertions using Equals-override for comparing objects equivalence. And it worked nice for the most of cases, but has introduced another issue - now FluentAssertions seem to ignore the option IgnoreCyclicReferences()
Complete minimal example reproducing the issue
Here is the minimal example I could make to reproduce the issue:
[TestFixture]
public class FluentAssertionsIssueTest {
public class Base {
public Guid Id { get; set; }
// NHibernate recommends overriding Equals for preventing issues with Sets and while working with multiple sessions, as well as issues with proxies in collections
public override bool Equals(object obj) {
if (ReferenceEquals(this, obj))
return true;
return (obj is Base baseObj) && baseObj.Id == Id;
}
}
public class Item : Base {
public string Title { get; set; }
public Item Previous { get; set; }
public Item Next { get; set; }
}
[Test]
public void IgnoreCyclicReferences_Broken() {
// imitating NHibernate save in one session
var first = new Item() {Id = Guid.NewGuid(), Title = "First"};
var second = new Item() {Id = Guid.NewGuid(), Title = "Second", Previous = first};
first.Next = second;
// imitating NHibernate load in another session
var firstCopy = new Item() {Id = first.Id, Title = first.Title};
var secondCopy = new Item() {Id = second.Id, Title = second.Title, Previous = firstCopy};
firstCopy.Next = secondCopy;
// I'd like to check, that all the properties could be persisted correctly.
// "The maximum recursion depth was reached" is generated here (IgnoringCyclicReferences doesn't seem to work)
firstCopy.Should().BeEquivalentTo(first, opt => opt.ComparingByMembers<Base>()
.IgnoringCyclicReferences(), "they are equivalent");
first.Title = "Changed";
// Removing Equals-override from Base class fixes FA issues, but introduces NHibernate-issues
// Removing ComparingByMembers-option removes "The maximum recursion depth was reached", but breaks this check (changed Title is not considered)
firstCopy.Should().NotBeEquivalentTo(first, opt => opt.ComparingByMembers<Base>()
.IgnoringCyclicReferences(), "after change");
}
}Expected behavior:
Deep object comparison should be done, handling cyclic references correctly. The test should pass
Actual behavior:
I cannot use deep object comparison on objects with overridden Equals and cyclic references.
The test fails with message:
The maximum recursion depth was reached.
The maximum recursion depth was reached.
The maximum recursion depth was reached.
The maximum recursion depth was reached.
With configuration:
- Use declared types and members
- Compare enums by value
- Ignoring cyclic references
- Match member by name (or throw)
- Without automatic conversion.
- Be strict about the order of items in byte arrays
bei FluentAssertions.Execution.LateBoundTestFramework.Throw(String message)
bei FluentAssertions.Execution.CollectingAssertionStrategy.ThrowIfAny(IDictionary`2 context)
bei FluentAssertions.Equivalency.EquivalencyValidator.AssertEquality(EquivalencyValidationContext context)
If I comment out override Equals everything works in FA, but introduces issues with NHibernate.
If I remove options ComparingByMembers<Base>() in both BeEquivalentTo / NotBeEquivalentTo, then the difference of Title in firstCopy and first is not detected in the NotBeEquivalentTo-Check.
Versions
- 5.10.3, 5.10.2
- Using .NET framework 4.6.1