6

I have 2 dictionaries and I would expect the contents not to be equivalent as the dictionary contains values of different types. However the following test passes

[Scenario]
public void DictionariesWithDifferentTypesShouldBeEquivalent(
    Dictionary<string, object> firstDictionary, 
    Dictionary<string, object> secondDictionary)
{
    "Given a dictionary"
        .f(() => firstDictionary = new Dictionary<string, object> 
                    {
                        { "latency", 0 },
                        { "errorMessages", new string[0] },
                        { "lastChanged", new DateTime(635272310930829706) },
                        { "query", new string[0] },
                        { "items", new string[] { "foo", "bar" } },
                        { "name", "Bob" },
                        { "number", 3 },
                        { "updateInterval", 10 },
                    });

    "And a second dictionary with same values but of differing types"
        .f(() => secondDictionary = new Dictionary<string, object> 
                    {
                        { "latency", 0L },
                        { "errorMessages", new object[0] },
                        { "lastChanged", new DateTime(635272310930829706) },
                        { "query", new string[0] },
                        { "items", new string[] { "bar", "foo" } },
                        { "name", "Bob" },
                        { "number", 3 },
                        { "updateInterval", "10" },
                    });

    "When I check for equivalency"
        .f(() => { });

    "Then the dictionaries should be equivalent"
        .f(() => firstDictionary.ShouldBeEquivalentTo(secondDictionary));
}

If this is the expected behaviour how can I set up a fluent assertions rule to check that the type matches?

I have investigated using both a MatchingRule and an AssertionRule but in both cases I dont seem to have access to the original types of the subject and expected. It appears the the subject has already been converted to the type of the expected. I.e in the exapmle above updateInterval in the first dictionary would already have been converted to a string for comparison with the second dictionary.

Thanks for the help,
Rachael

Rachael
  • 61
  • 1
  • 2
  • 1
    This is by design. By default it'll do a recursive structural comparison which ignores the order of the items in collections and try to convert the actual values to the expected values. Which specific path should it fail on? – Dennis Doomen Jun 12 '14 at 23:57
  • If you don't answer my question, I can't provide you with a solution. – Dennis Doomen Jul 14 '14 at 06:26
  • 1
    Is there any way to force the comparison to take the types into consideration? For example, WithStrictOrdering can be used to require nested collections to have the same ordering, changing the default behavior. Would there be a way to say "nested objects need to be equivalent, including their types", so that if you happen to have a derived class without extra properties they would be considered non-equivalent? – fpintos Jun 10 '16 at 23:53
  • Does this help? https://github.com/fluentassertions/fluentassertions/issues/798#issuecomment-624113357 – arni May 05 '20 at 15:29

3 Answers3

1

But they are equivalent. Both dictionaries contain the same keys and values that are deemed to be equivalent. 0L and 0 can be converted to the same type and therefor are equivalent. And for the record, ShouldBeEquivalentTo doesn't do a reference equality check persee. But if the subject and expectation are the same object, then yes, it can safely assume they are equivalent as well.

Dennis Doomen
  • 8,368
  • 1
  • 32
  • 44
0

[This question is nearly a year old, but I found it when looking for an answer to the same question]

Allow my to alter the question slightly:

How Do I Check for Type using FluentAssertions?

The FluentAssertions "ShouldBeEquivelentOf" is a reference check to see if objects are 'the same' (byRef)

The proper FluentAssertions call is just "Should().Be(...) as objectList.GetType().Should().Be(typeof(List<Classes.SomeListObject>));

Cos Callis
  • 5,051
  • 3
  • 30
  • 57
0

Version 5.0.0-beta.1 of the library now supports Should().BeEquivalentTo() without type conversion out of the box.

https://github.com/fluentassertions/fluentassertions/releases/tag/5.0.0-beta.1 https://github.com/fluentassertions/fluentassertions/pull/616

You can opt in to type conversion by using WithAutoConversion().

KangarooWest
  • 768
  • 2
  • 7
  • 20
  • 1
    I am trying to compare graphs of objects and want it to use only properties values and class names to match. FA passes with new AbsoluteLink("path").Shold().BeEuivalentTo(new RelativeLink("path")) I expect it to say that class names do not match – AxCoder Mar 10 '18 at 12:03