【问题标题】:FluentAssertions - how to exclude comparison of dictionary keys?FluentAssertions - 如何排除字典键的比较?
【发布时间】:2018-09-02 00:13:13
【问题描述】:

使用Should().BeEquivalentTo() 我想比较两个包含一系列键值对的对象,但要排除键的实际值,因为这会有所不同。所以基本上我只对比较值的内容感兴趣。 示例:

MyObject { MyDictionary1 { Key, Value } ... MyDictionary2 { Key, Value } }

相比

ExpecterdObject { ExpectedDictionary1 { Key, Value } ... ExpectedDictionary2 { Key, Value } }

这两个对象属于同一个类,具有相同的结构,但每个实例都有唯一的 ID 作为键。

我已经试过了

.Excluding(e => e.KayValuePair.Keys)

这似乎不起作用,因为我仍然收到错误提示

预期成员 MyDictionary1 是包含 3 个项目的集合。预期的 成员 MyDictionary1 包含密钥 X。

【问题讨论】:

  • 你能提供一个完整的例子和示例数据吗?

标签: key-value keyvaluepair fluent-assertions


【解决方案1】:

如果您有一个像MyClass 这样的对象结构,并且您想要覆盖Dictionary 属性在MyClass 的两个实例之间的比较方式。即只比较字典中的Values

class MyClass
{
    public int Value { get; set; }

    public Dictionary<int, string> Dictionary1 { get; set; }

    public Dictionary<int, string> Dictionary2 { get; set; }
}

为此,您可以使用documentation 中的UsingWhenTypeIs 的组合。

这是您案例的完整示例,其中字典具有相同的 Values,但 Keys 不同。

public void MyTestMethod()
{
    var expected = new MyClass
    {
        Value = 42,
        Dictionary1 = new Dictionary<int, string>
        {
            [1] = "foo",
            [2] = "bar"
        },
        Dictionary2 = new Dictionary<int, string>
        {
            [3] = "bar",
            [4] = "baz"
        }
    };

    var actual = new MyClass
    {
        Value = 42,
        Dictionary1 = new Dictionary<int, string>
        {
            [5] = "foo",
            [6] = "bar",
        },
        Dictionary2 = new Dictionary<int, string>
        {
            [7] = "bar",
            [8] = "baz",
        }
    };

    actual.Should().BeEquivalentTo(expected, options => options.
        Using<Dictionary<int, string>>(ctx => ctx.Subject.Values.Should().BeEquivalentTo(ctx.Expectation.Values))
        .WhenTypeIs<Dictionary<int, string>>());
}

【讨论】:

  • 实际上我想做相反的事情:从比较中排除键,只比较值。当然我可以做 MyDictionary.Values.Should().BeEquivalentTo(ExpectedDictionary.Values) 但我想在比较包含大量字典的 2 个对象时这样做,而不是单独比较每个字典。
  • @FSatmar 我已经更新了示例显示,它概括为包含多个字典的对象。
【解决方案2】:

对于最近遇到此问题的任何人,当我的公司使用具有唯一字符串的字典作为键时,我也遇到了同样的问题。我能够通过编写自定义 IEquivalencyStep 来解决它。

    public class DictionaryComparer : IEquivalencyStep
    {
        public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config)
        {
            return context.Subject is IDictionary &&
                context.Expectation is IDictionary;
        }

        public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
        {
            var actual = (IDictionary)context.Subject;
            var expected = (IDictionary)context.Expectation;
            var actualValues = actual.Values;
            var expectedValues = expected.Values;

            actualValues.Should().BeEquivalentTo(expectedValues, options => options
            // Other exclusions, options, etc.
            );

            return true;
        }
    }

然后无论您在哪里进行 FA 等效性检查:

actual.Should().BeEquivalentTo(expected, options => options
.Using(new DictionaryComparer())
// Continue with other exclusions, options, etc...
);

实现后,父对象中的所有字典都将通过您设置的自定义比较器进行检查。您可以更改 CanHandle 重载以查找您想要的任何条件,然后仅在满足它们时才返回 true。这将导致从 CanHandle 方法返回 true 的对象通过它下面的 Handle() 方法进行评估。

注意:这在 FluentAssertions 5 中有效,但我不确定这是否在版本 6 中发生了变化。

【讨论】:

    猜你喜欢
    • 2021-06-02
    • 1970-01-01
    • 2022-01-09
    • 2019-07-14
    • 1970-01-01
    • 2014-03-03
    • 1970-01-01
    • 2018-09-25
    • 2016-10-02
    相关资源
    最近更新 更多