使用NUnit断言集合中的所有项都具有某个项属性的值。

7

我需要将 MS 单元测试转换为 NUnit 测试,并遇到了这个断言。

Assert.AreEqual(collection.Select(item => item.location.id).Distinct().Count(), 1);

我希望有一种优雅的方式可以使用约束条件来编写它,但是我没有找到。我的解决方案是这样的,但我并不是很满意:

Expect(collection.Select(item => item.location.id).Distinct().Count(), Is.EqualTo(1));

有没有更好的方式编写这个断言,使意图更明确易读?(使用 Has.Map(collection).
编辑2: 我刚意识到清楚地说明意图可能有所帮助:
收集中的所有项目具有相同的位置ID(不知道该ID是什么)
编辑1: 这就是集合可能看起来像JSON:
[{itemId=1, location={name="A", id=1}},
 {itemId=2, location={name="A", id=1}},
 {itemId=3, location={name="A", id=1}}]

distinct.count = 1     => pass

[{itemId=1, location={name="A", id=1}},
 {itemId=2, location={name="A", id=1}},
 {itemId=4, location={name="B", id=2}}]

distinct.count = 2 => 失败

编辑3:基于Fabio的答案我的最终解决方案

IEnumerable<long?> locationIds = collection.Select(item => item.location.id);
Expect(locationIds, Has.All.EqualTo(locationIds.FirstOrDefault()));

你希望所有的项都是唯一的吗?你能否发布一个集合可能看起来像什么的示例? - Dr Schizo
@MoeGhafari 很好的发现。事实上,唯一会失败的方式是如果列表为空,因为条件始终为真。 - Dr Schizo
@MoeGhafari 我刚刚添加了集合可能看起来像什么;这是为了确保所有项目都在同一位置。 - Holly
@DrSchizo 在我的理解中,Select(item => item.location.id) 投影出每个项目的位置 ID 作为一个新列表,Distinct() 将会去除所有重复项,然后 count 将返回集合中唯一位置 ID 的数量。 - Holly
@Holly,然而正如之前提到的,这个测试没有任何价值。你有一个列表,并在测试中对列表进行过滤。你在这里没有测试任何业务逻辑。你正在测试.NET是否按照应该的方式工作。 - Dr Schizo
显示剩余2条评论
3个回答

12

可读版本

int expectedCount = 1;
int actualCount = collection.Select(item => item.location.id)
                            .Distinct()
                            .Count()

Assert.AreEqual(expectedCount, actualCount);

我不确定,但你可以尝试这个版本,其中短语 "Is all equal to..." 应该有助于 "非程序员",并让你的代码摆脱 "神奇数字"

var value = collection.Select(item => item.location.id).FirstOrDefault();
Assert.That(collection.Select(item => item.location.id), Is.All.EqualTo(value));

抱歉,对我来说这并没有更好;我希望能够使用NUnit约束API而不仅仅是重新格式化该lambda表达式,我希望有些东西是非程序员也能阅读和理解的。 - Holly
似乎以上是最简单的。请参考Mark Seeman的回答https://dev59.com/KI_ea4cB1Zd3GeqPScGN#32936435 - Dr Schizo
@Holly,Is.All.EqualTo是另一种断言集合包含具有相同location.id的项的方法。还有Has.Exact约束可用于不同值的计数。 - Fabio
@Fabio 嗯,这两个是我最初的猜测,也是我想要的;问题是,我不知道位置 ID 需要等于多少值,只知道所有位置 ID 必须相同。 - Holly
@Holly,如我所示的答案,您可以从集合中检索第一个值,然后将其与集合中的其他值进行比较。 - Fabio
1
@Fabio 我猜你的第二个答案是我能得到的最接近的,尽管我不喜欢做两次相同的投影,所以我稍微改了一下 - 请看我的第三个编辑 - 谢谢。 - Holly

8
如果我理解你想要做的事情...这应该可以实现...
Assert.That(collection.Select(() => item.location.id), Is.Unique);

留下这个错误的答案...可能有人想测试独特性,但那不是这个人想要的!!!

2
哦等等!我还没明白。你想要唯一的相反数。 :-) - Charlie
实际上这是流畅语法中的一个漏洞,尽管多年来没有人提出过这个问题,所以可能并不重要。请随意请求功能。 - Charlie
我也需要这个功能。 'Is.All.Not.Unique' 是错误的吗? - Denis535
这正是我今天在寻找的东西 ;) - scar80
真是我想要的!:) - ANewGuyInTown

0

根据您的示例数据,注意到当Id相等时name也相等,您可以使用以下代码:

var distinctLocations = collection.select(item => item.location).Distinct();

Assert.That(distinctLocations, Has.Exactly(1).Items);

如果这个假设是不正确的,你当然需要仅提取 id


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接