diff --git a/Src/FluentAssertions/Common/MemberPath.cs b/Src/FluentAssertions/Common/MemberPath.cs index f3618c91c8..c981d94194 100644 --- a/Src/FluentAssertions/Common/MemberPath.cs +++ b/Src/FluentAssertions/Common/MemberPath.cs @@ -11,9 +11,9 @@ namespace FluentAssertions.Common /// internal class MemberPath { - private readonly string dottedPath; - private readonly Type reflectedType; - private readonly Type declaringType; + private string dottedPath; + private Type reflectedType; + private Type declaringType; private string[] segments; @@ -38,6 +38,10 @@ public MemberPath(string dottedPath) this.dottedPath = dottedPath; } + private MemberPath() + { + } + /// /// Gets a value indicating whether the current object represents a child member of the /// or that it is the parent of that candidate. @@ -96,6 +100,19 @@ public bool HasSameParentAs(MemberPath path) /// public bool GetContainsSpecificCollectionIndex() => dottedPath.ContainsSpecificCollectionIndex(); + /// + /// Returns a copy of the current object as if it represented an un-indexed item in a collection. + /// + public MemberPath WithCollectionAsRoot() + { + return new MemberPath + { + dottedPath = "[]." + dottedPath, + reflectedType = reflectedType, + declaringType = declaringType + }; + } + private string[] Segments => segments ??= dottedPath.Split(new[] { '.', '[', ']' }, StringSplitOptions.RemoveEmptyEntries); /// diff --git a/Src/FluentAssertions/Equivalency/Matching/MappedPathMatchingRule.cs b/Src/FluentAssertions/Equivalency/Matching/MappedPathMatchingRule.cs index 305695558d..d710ac0e98 100644 --- a/Src/FluentAssertions/Equivalency/Matching/MappedPathMatchingRule.cs +++ b/Src/FluentAssertions/Equivalency/Matching/MappedPathMatchingRule.cs @@ -35,7 +35,13 @@ public MappedPathMatchingRule(string expectationMemberPath, string subjectMember public IMember Match(IMember expectedMember, object subject, INode parent, IEquivalencyAssertionOptions options) { - if (expectationPath.IsEquivalentTo(expectedMember.PathAndName)) + MemberPath path = expectationPath; + if (expectedMember.RootIsCollection) + { + path = path.WithCollectionAsRoot(); + } + + if (path.IsEquivalentTo(expectedMember.PathAndName)) { var member = MemberFactory.Find(subject, subjectPath.MemberName, expectedMember.Type, parent); if (member is null) diff --git a/Tests/FluentAssertions.Equivalency.Specs/MemberMatchingSpecs.cs b/Tests/FluentAssertions.Equivalency.Specs/MemberMatchingSpecs.cs index 2a813ea8ef..3f313839ef 100644 --- a/Tests/FluentAssertions.Equivalency.Specs/MemberMatchingSpecs.cs +++ b/Tests/FluentAssertions.Equivalency.Specs/MemberMatchingSpecs.cs @@ -475,6 +475,44 @@ public void Mapping_works_with_exclusion_of_missing_members() ); } + [Fact] + public void Can_map_members_of_a_root_collection() + { + // Arrange + var entity = new Entity + { + EntityId = 1, + Name = "Test" + }; + + var dto = new EntityDto + { + Id = 1, + Name = "Test" + }; + + var entityCol = new[] { entity }; + var dtoCol = new[] { dto }; + + // Act / Assert + dtoCol.Should().BeEquivalentTo(entityCol, c => + c.WithMapping(s => s.EntityId, d => d.Id)); + } + + private class Entity + { + public int EntityId { get; init; } + + public string Name { get; init; } + } + + private class EntityDto + { + public int Id { get; init; } + + public string Name { get; init; } + } + internal class ParentOfExpectationWithProperty2 { public ExpectationWithProperty2[] Parent { get; } diff --git a/docs/_pages/releases.md b/docs/_pages/releases.md index c3f0021dcb..be536b9c60 100644 --- a/docs/_pages/releases.md +++ b/docs/_pages/releases.md @@ -18,6 +18,7 @@ sidebar: * `EnumAssertions.Be` did not determine the caller name - [#1835](https://github.com/fluentassertions/fluentassertions/pull/1835) * Ensure `ExcludingMissingMembers` doesn't undo usage of `WithMapping` in `BeEquivalentTo` - [#1838](https://github.com/fluentassertions/fluentassertions/pull/1838) * Better handling of NaN in various numeric assertions - [#1822](https://github.com/fluentassertions/fluentassertions/pull/1822) +* `WithMapping` in `BeEquivalentTo` now also works when the root is a collection - [#1858](https://github.com/fluentassertions/fluentassertions/pull/1858) ### Fixes (Extensibility)