AssertJ和集合简介

An Intro to AssertJ and Collections

使用Java进行编程时,您通常最终会编写返回对象集合的方法。 它们当然在您的应用程序中占有一席之地,但是对其进行测试可能会有些棘手。 根据基础集合的实现,元素的顺序可能不同,集合上的equals并不总是显而易见的,依此类推。 在我的职业生涯中,我遇到过多个此类案例的示例,我决定选择其中的几个案例,并展示一种使用AssertJ(您肯定应该使用的断言库)解决此类问题的方法。

所有食谱都遵循相同的格式。 我给出一个简短的描述,然后执行测试。 测试始终是成功的,以避免混淆。 每个食谱都以简短的注释结尾,就像可以用于其他情况一样。 我还使用了Guava库来创建集合,因为香草Java并没有真正提供实现此目的的方法。

为了进行测试,我们可以使用某些Java原语,例如Stringint,但是在野外,这种情况很少见。 假设我们正在制作RPG游戏,因此我们将拥有很多POJO,分别代表游戏中的不同角色和对象。 例如,代表怪物的类:

1
2
3
4
5
6
7
8
public class Monster {
    private String id;
    private String name;

    // constructor for all arguments
    // getters and setters
    // equals based on id and hashCode
}

模型和测试的代码都可以作为agist使用。

集合包含预期元素

让我们从最简单的一个开始。 您要确保从一种方法返回的列表包含您感兴趣的一个或多个元素。 AssertJ允许您使用contains方法及其负的对等物doesNotContain实现这一目标。 该方法检查给定元素是否在集合中:

1
2
3
4
5
6
7
assertThat(beasts).contains(direwolf);
assertThat(beasts).contains(werewolf);

// the same
assertThat(beasts).contains(werewolf, direwolf);

assertThat(beasts).doesNotContain(vampire);

前两行检查direwolfwerewolf是否属于beasts集合。 如您在下一行中看到的,您还可以验证多个元素。

要记住的一件事是该方法既不在乎所有元素(即,它也不检查是否还有其他元素)或顺序。

收藏包含我感兴趣的所有元素,无所谓

生成集合时,通常不需要关心元素的顺序。 这是containsExactlyInAnyOrder有用的地方:

1
2
assertThat(beasts).containsExactlyInAnyOrder(direwolf, werewolf);
assertThat(beasts).containsExactlyInAnyOrder(werewolf, direwolf);

假定元素的数量完全相同,但是顺序不起作用。 您可以使用containsExactlyElementsOf(采用Iterable)来实现相似的目标,但是效果并不理想。

集合按给定顺序包含我感兴趣的所有元素

这与上一个类似,但是没有...InAnyOrder(duh!):

1
2
3
4
assertThat(beasts).containsExactly(direwolf, werewolf);

// this one is false this time
// assertThat(beasts).containsExactly(werewolf, direwolf);

集合仅包含给定元素

这听起来与第一个相似,但有一点不同:我们不在乎计数,我们只在乎是否还有其他元素:

1
2
3
4
List<Monster> group = Lists.newArrayList(direwolf, direwolf, werewolf, werewolf, werewolf);

assertThat(group).containsOnly(direwolf, werewolf);
assertThat(group).containsOnly(werewolf, direwolf);

例如,这对于可能可能重复多次的枚举集合很有用。 请记住,这不会检查任何订单!

元素仅出现一次的集合

这听起来与上一个相似。 即使该方法的名称也类似:containsOnlyOnce。 但是,其背后的想法却截然不同。 虽然containsOnly检查集合中是否没有其他元素,但此元素检查给定元素是否存在于集合中(就像contains一样),并且它仅出现一次:

1
2
3
4
5
6
7
List<Monster> group = Lists.newArrayList(direwolf, direwolf, werewolf, vampire);

assertThat(group).containsOnlyOnce(vampire);
assertThat(group).containsOnlyOnce(werewolf);

// this one is false
// assertThat(group).containsOnlyOnce(direwolf);

听起来有个好主意,那就是有一种方法可以让您验证更复杂的计数,但是不幸的是,在撰写本文时,还没有这样的方法。

具有给定属性的元素的集合

现在,这很酷(因为我写的很酷)。 当您要检查集合中是否包含已将给定属性设置为期望值的元素时,可以使用extracting方法。 使用Java 8 lambda函数,可以大大提高可读性:

1
2
assertThat(beasts).extracting(Monster::getName)
                  .containsExactly("direwolf","werewolf");

补充方法是flatExtracting。 它用于返回List的属性,并实际上合并这些属性中的列表。

上述配方是编写返回集合的方法的测试的最常见用例。 如果您觉得我缺少什么,请告诉我!