如何使用在FluentAssertions中排除以排除Dictionary

时间:2017-11-15 20:18:13

标签: c# dictionary fluent-assertions

我使用带有ShouldBeEquivalentTo的FluentAssertions来比较两个类型为Dictionary<string, string>的词典,但希望排除一个或多个特定的KeyValue对(因为它们在这种情况下包含时间戳)。怎么做?

我尝试了类似:opt => opt.Excluding(x => x.Single(kv => kv.Key == "MySearchKey"))的内容,但这会导致错误:Message: System.ArgumentException : Expression <Convert(x.Single(kv => (kv.Key == "MySearchKey")))> cannot be used to select a member.

我想要的是什么?或者我是否应该仅排除该值而不是该对(这可能更好,因为将检查密钥的存在)?谢谢!

1 个答案:

答案 0 :(得分:1)

Excluding()用于排除类型的成员,不排除集合的成员,有关详细信息,请参阅documentation。< / p>

注意:下面的代码适用于Fluent Assertions的当前稳定版本4.19.4。

实施例: 您想比较PersonPersonDTO的实例,但Person包含您要从对象比较中排除的AnotherProperty

var person = new Person
{
    FirstName = "John",
    LastName = "McClane",
    AnotherProperty = 42
};

var personDTO = new PersonDTO
{
    FirstName = "John",
    LastName = "McClane"
};

您可以使用Exclude排除某个类型的成员。

person.ShouldBeEquivalentTo(personDTO, options => options.Excluding(e => e.AnotherProperty));

在具体案例中,我不会使用ShouldBeEquivalentTo。 考虑这两个字典实例,您要在其中省略集合的成员,此处为Key == "unknown"成员。

var actual = new Dictionary<string, int>
{
    ["one"] = 1,
    ["two"] = 2,
    ["three"] = 3,
    ["unknown"] = -1,
    ["fail"] = -2
};

var expected = new Dictionary<string, int>
{
    ["one"] = 1,
    ["two"] = 2,
    ["three"] = 3
};

您可以直接过滤掉不需要的键值对:

IEnumerable<KeyValuePair<string, int>> filtered = actual.Where(e => e.Key != "unknown");

现在断言将介于两个IEnumerable<KeyValuePair<string, int>> s

之间
filtered.Should().Equal(expected);

将给出以下断言失败消息:

FluentAssertions.Execution.AssertionFailedException: 'Expected collection to be equal to {[one, 1], [two, 2], [three, 3]}, but {[one, 1], [two, 2], [three, 3], [fail, -2]} contains 1 item(s) too many.'

否则将过滤后的可枚举变回字典:

Dictionary<string, int> filteredDict = actual.Where(e => e.Key != "unknown")
    .ToDictionary(e => e.Key, e => e.Value);

您现在将再次比较Dictionary<string, int>

filteredDict.Should().Equal(expected);

将给出以下断言失败消息:

FluentAssertions.Execution.AssertionFailedException: 'Expected dictionary to be equal to {[one, 1], [two, 2], [three, 3]}, but found additional keys {"fail"}.'

如果想要使用第二种方法而且经常这样做,您可以创建扩展方法来提取从测试方法中删除成员的逻辑。

public static class DictionaryExtensions
{
    public static IDictionary<TKey, TValue> ExceptKeys<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, params TKey[] keys)
    {
        if (dictionary == null) throw new ArgumentNullException(nameof(dictionary));
        if (keys == null) throw new ArgumentNullException(nameof(keys));

        return dictionary.Where(e => !keys.Contains(e.Key)).ToDictionary(e => e.Key, e => e.Value);
    }

    public static IDictionary<TKey, TValue> ExceptValues<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, params TValue[] values)
    {
        if (dictionary == null) throw new ArgumentNullException(nameof(dictionary));
        if (values == null) throw new ArgumentNullException(nameof(values));

        return dictionary.Where(e => !values.Contains(e.Value)).ToDictionary(e => e.Key, e => e.Value);
    }
}

您现在可以在我看来更清晰简洁地测试:

actual.ExceptKeys("unknown").Should().Equal(expected);