如何检查对象集合是否包含给定顺序的对象属性

How to check if an Object collection contains an Object properties in given order

假设我有一本书集。(这本书是从 Elastic Search 中获取的)

class Book {

String name;
String author;

// 10 other properties

}

现在在我的 JUnit 中,我需要测试书籍是否按 name 的升序排列(最近我需要对所有其他 11 个属性进行相同的测试)

在我的 JUnit 测试 class 中是否可以在不创建 Book 对象的情况下测试 book 的顺序?如果是怎么办?

这不是特定于 JUnit 的,但也许 this answer 在这方面有帮助:

它建议使用这种通用方法:

public static <T extends Comparable<? super T>> boolean isSorted(final Iterable<T> iterable) {
    Iterator<T> iter = iterable.iterator();
    if (!iter.hasNext()) {
        return true;
    }
    T t = iter.next();
    while (iter.hasNext()) {
        T t2 = iter.next();
        if (t.compareTo(t2) > 0) {
            return false;
        }
        t = t2;
    }
    return true;
}

查看用于测试的 AssertJ 库,您可以使用它来确定示例列表是否有序

首先从书中提取名字:

List<String> names = books.stream()
                          .map(book -> book.getName())
                          .collect(Collectors.toList());

随后使用 AssertJ 方法测试订单,如:

Assertions.assertThat(names).isSorted()

当然你也可以提供自己的比较器,使用isSortedAccordingTo方法

供参考 http://joel-costigliola.github.io/assertj/core/api/org/assertj/core/api/ArraySortedAssert.html

注意:我没有尝试编译代码

我认为基本上有两种选择:您可以使用一个库来使(某些)测试的编写更加方便,并且您可以依靠简单的 JUnit 并“手动”完成其他所有操作”.

对于图书馆选项,这不是我的专长,但我知道有很多选择。 pezetem 在 中写的关于 AssertJ 的内容听起来很有前途,尤其是 isSortedAccordingTo()。不过,它确实需要您为每个要检查的排序编写一个 Comparator。在做出明智的选择之前,我会仔细查看不同的库,并着眼于除此之外的其他测试。

如果你现在不想依赖库,我建议你自己写一个这样的辅助方法:

private static <T extends Comparable<? super T>> boolean isSortedBy(Function<Book, T> getMethod, List<Book> list) {
    if (list.isEmpty()) {
        return true;
    }
    Iterator<Book> bit = list.iterator();
    T attr = getMethod.apply(bit.next());
    while (bit.hasNext()) {
        T nextAttr = getMethod.apply(bit.next());
        if (nextAttr.compareTo(attr) < 0) {
            return false;
        }
        attr = nextAttr;
    }
    return true;
}

您会认出 中的逻辑,但我在这里扭曲了方法签名以满足您的需要。现在您的测试很简单:

    assertTrue(isSortedBy(Book::getName, listOfBooks));

不过有两个注意事项:

  1. 我假设你的 Book class 有吸气剂,你可能想要添加它们是有原因的,不仅仅是为了单元测试。如果没有,您可以使用 isSortedBy(b -> b.name, listOfBooks).
  2. 当您说集合时,我假设您指的是列表。其他集合类型(如集合)可能没有顺序,因此检查它们是否已排序可能没有意义。

如果您希望您的方法更通用,您可以添加另一个类型参数以允许列出书籍以外的其他内容:

private static <E, T extends Comparable<? super T>> boolean isSortedBy(Function<E, T> getMethod, List<E> list)

就我而言,我会等到我看到需要为止。

在编写单元测试时,我发现值得考虑如何向测试人员报告测试失败,如果测试失败,s/he 需要什么信息。只知道列表没有按照它应该排序的属性排序可能没有那么有用。除非你的列表很长,否则我认为你可以将整个列表转储为消息:

    assertTrue(listOfBooks.toString(), isSortedBy(Book::getName, listOfBooks));

(您需要确保您的 Book class 有一个 toString 方法才能发挥作用。)当然有一些方法可以进行更精细的故障报告,如果你有辅助方法 return 一个特定的消息而不仅仅是 truefalse.