The Fluent Assertions library puts quite some emphasis on its capabilities of comparing object graphs by means of the Should().BeEquivalentTo
method and related methods. As the documentation points out:
Should().BeEquivalentTo
is a very powerful feature, and one of the unique selling points of Fluent Assertions.
From reading the examples, I am getting the impression that the object graph has to be connected by means of object references.
Now, I have plenty of object graphs and trees whose content I would like to check, but they are usually loaded from files or from databases. Therefore, the connection exists solely by ID property values that match across objects.
For instance, imagine this simple structure (here written in JSON format) - example A:
[{
"Id": 1,
"Name": "Foo",
"NextId": 2
}, {
"Id": 2,
"Name": "Bar"
}]
I would like to use Fluent Assertions to check the structure of such an object graph.
That is, no matter what values the fields Id
and NextId
actually have, NextId
in the first object must have the same value as Id
in the second object.
Thus, any set of two objects with two different Id
values, where one object has a NextId
value that equals the Id
value of the other object, will do.
Example B:
[{
"Key": 5,
"LinkedTo": [3]
}, {
"Key": 10,
"LinkedTo": []
}, {
"Key": 3,
"LinkedTo": [5]
}]
Here, any set of three objects with three different Key
values, where two objects refer to each other's key in their LinkedTo
property and the remaining object has an empty array in its LinkedTo
property should match.
Example C:
[{
"Id": 1,
"Owner": 4
}, {
"Id": 2,
"Owner": 4
}, {
"Id": 3,
"Owner": 4
}, {
"Id": 4
}]
Here, any set of four objects with three different Id
values will match if three of those objects have an Owner
property whose value matches the Id
property of the remaining object.
Can this somehow be done with BeEquivalentTo
?
Note that I do not want to walk through my objects and add actual object references before applying any assertions, because that operation in itself might introduce bugs of its own.
EDIT: As requested, here are a couple of matching and non-matching graphs for the above examples:
Example A:
Match:
[{
"Id": 5,
"Name": "Foo",
"NextId": -8
}, {
"Id": -8,
"Name": "Bar"
}]
Match:
[{
"Id": 200,
"Name": "Bar"
}, {
"Id": 30,
"Name": "Foo",
"NextId": 200
}]
Mismatch:
[{
"Id": 3,
"Name": "Bar",
"NextId": 6
}, {
"Id": 6,
"Name": "Foo"
}]
Example B:
Match:
[{
"Key": 20,
"LinkedTo": [7]
}, {
"Key": 8,
"LinkedTo": []
}, {
"Key": 7,
"LinkedTo": [20]
}]
Match:
[{
"Key": 9,
"LinkedTo": [100]
}, {
"Key": 100,
"LinkedTo": [9]
}, {
"Key": 3,
"LinkedTo": []
}]
Mismatch:
[{
"Key": 5,
"LinkedTo": [10]
}, {
"Key": 10,
"LinkedTo": []
}, {
"Key": 3,
"LinkedTo": [5]
}]
Example C:
Match:
[{
"Id": 1
}, {
"Id": 2,
"Owner": 1
}, {
"Id": 3,
"Owner": 1
}, {
"Id": 4,
"Owner": 1
}]
Match:
[{
"Id": 10,
"Owner": 20
}, {
"Id": 30,
"Owner": 20
}, {
"Id": 20
}, {
"Id": 40,
"Owner": 20
}]
Mismatch:
[{
"Id": 8,
"Owner": 2
}, {
"Id": 12,
"Owner": 8
}, {
"Id": 54,
"Owner": 2
}, {
"Id": 2
}]