如何使用 Fluent Assertion 比较因属性而异的两个集合?

aba*_*hev 4 c# unit-testing fluent-assertions

我有RuleInfo从内部类创建的公共类Rule

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

它们的属性名称各不相同,因此ShouldBeEquivalentTo()ShouldAllBeEquivalentTo()不起作用。

现在我正在手动/明确地比较它们:

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
        });
}
Run Code Online (Sandbox Code Playgroud)

有没有更好、更紧凑、更简洁、更易读的方式?

Evk*_*Evk 6

一种选择是向全局选项配置添加自定义等效步骤:

class DifferentObjectsEquivalencyStep<T1, T2> : IEquivalencyStep {
    private readonly Func<T1, T2> _converter;

    public DifferentObjectsEquivalencyStep(Func<T1, T2> converter) {
        _converter = converter;
    }

    public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) {
        return context.Subject is T1 && context.Expectation is T2 || context.Subject is T2 && context.Expectation is T1;
    }

    public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config) {            
        var first = context.Subject is T1 ? (T1) context.Subject : (T1) context.Expectation;
        var second = context.Subject is T2 ? (T2) context.Subject : (T2) context.Expectation;
        second.ShouldBeEquivalentTo(_converter(first));
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你做所有比较之前的某个地方:

AssertionOptions.AssertEquivalencyUsing(c => c.Using(
            new DifferentObjectsEquivalencyStep<Rule, RuleInfo>(CreateRuleInfo)));
Run Code Online (Sandbox Code Playgroud)

之后,常规ShouldBeEquivalentTo(和ShouldAllBeEquivalentTo)将起作用:

rule.ShouldBeEquivalentTo(info);
Run Code Online (Sandbox Code Playgroud)