使用 AssertJ 断言列表仅包含 class 的一个实例

Assert List contains only one instance of a class using AssertJ

我能否以某种方式使用 AssertJ 断言一个列表只有一个 (sub)class 实例?

public class A {}
public class B extends A {}
public class C extends A {}

@Test
public void test() {
  List<A> list = new ArrayList<A>();
  list.add(new B());

  Assertions.assertThat(list).containsOnlyOnce(B.class);
}

你的代码的问题是 list 的类型是 A, 但是您尝试使用 containsOnlyOnce 验证的元素类型是 Class<B>

您需要使用相应的类型。 例如,您可以提取列表中的 类:

Stream<Class<?>> classes = list.stream().map(x -> x.getClass());
Assertions.assertThat(classes).containsOnlyOnce(B.class);

您需要定义一个Condition

以下将断言 list 仅包含一个 B.class 类型的对象引用。

Condition condition = new Condition() {
    @Override
    public boolean matches(Object o) {
        return o.getClass() == B.class;
    }};

Assertions.assertThat(list).areExactly(1, condition);

以下情况会失败:

list.add(new B());
list.add(new B());

还有

B b = new B();
list.add(b);
list.add(b);

使用Java 8 Stream API 可以实现像

long countOfClassB = list.stream().filter(t -> t instanceof B).count();
Assertions.assertThat(countOfClassB).isEqualTo(1L);

我会按原样使用 AssertJ extracting feature

assertThat(list).extracting("class")
                .containsOnlyOnce(B.class);

有一个方法hasOnlyElementsOfType(Class),它验证Iterable中的所有元素都具有指定的类型(包括给定类型的子类)。

解决方案可能如下所示:

assertThat(list).hasOnlyElementsOfType(B.class).hasSize(1);