Search code examples
c#unit-testingfluent-assertions

How to compare two collections that vary by properties using Fluent Assertion?


I have public class RuleInfo which is created from internal class Rule.

private static RuleInfo CreateRuleInfo(Rule r)
{
    return new RuleInfo
    {
        RuleCode = r.RuleId,
        DisplayName = r.RuleCode,
        Description = r.Description,
        LegacyRuleCode = null
    };
}

They vary in their properties names so ShouldBeEquivalentTo() or ShouldAllBeEquivalentTo() don't work.

Right now I'm comparing them manually/explicitly:

foreach (var x in Enumerable.Zip(infs, rules, (i, r) => new { Info = i, Rule = r }))
{
    x.Info.ShouldBeEquivalentTo(
        new
        {
            RuleCode = x.Rule.RuleId,
            DisplayName = x.Rule.RuleCode,
            Description = x.Rule.Description,
            LegacyRuleCode = (string)null
        });
}

Is there a better, more compact, less explicit, more readable way?


Solution

  • Unfortunately there currently isn't a way to specify a mapping between properties when comparing different types. There is an open issue about it.

    Here's an example on another way to compare two collections. Be aware that I'm assuming that == performs value equality. So if all your properties are int and string you are home safe.

    ruleInfos.Should().Equal(rules, (ruleInfo, rule) =>
        ruleInfo.RuleCode == rule.RuleId
         && ruleInfo.DisplayName == rule.RuleCode
        && ruleInfo.Description == rule.Description
    );
    

    For e.g. a reference type with no overload of == you would need to handle null values gracefully with e.g.

    (PropertyA == PropertyB) || (PropertyA?.Equals(PropertyB) == true