如何在 Fluent Assertions 中使用 Excluding 来排除 Dictionary 中的特定键值对
How to use Excluding in FluentAssertions to exclude specific KeyValue pair in Dictionary
我将 FluentAssertions 与 ShouldBeEquivalentTo
一起使用来比较两个 Dictionary<string, string>
类型的词典,但想排除一个或多个特定的键值对(因为在这种情况下它们包含时间戳)。如何做到这一点?
我试过类似的东西: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.
我想要的有可能吗?或者我应该只排除值而不是对(这可能更好,因为那时将检查密钥的存在)?谢谢!
Excluding()
用于排除 type 的成员,不排除 collection 的成员,参见 documentation 获取更多信息。
注:以下代码针对当前Fluent Assertions 4.19.4稳定版
示例:
您想要比较 Person
和 PersonDTO
的实例,但是 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
。
考虑这两个字典实例,您希望在其中省略 collection 的成员,这里是 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>
s:
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);
我将 FluentAssertions 与 ShouldBeEquivalentTo
一起使用来比较两个 Dictionary<string, string>
类型的词典,但想排除一个或多个特定的键值对(因为在这种情况下它们包含时间戳)。如何做到这一点?
我试过类似的东西: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.
我想要的有可能吗?或者我应该只排除值而不是对(这可能更好,因为那时将检查密钥的存在)?谢谢!
Excluding()
用于排除 type 的成员,不排除 collection 的成员,参见 documentation 获取更多信息。
注:以下代码针对当前Fluent Assertions 4.19.4稳定版
示例:
您想要比较 Person
和 PersonDTO
的实例,但是 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
。
考虑这两个字典实例,您希望在其中省略 collection 的成员,这里是 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>
s:
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);