assertThat - hamcrest - 检查列表是否排序
好吧,我认为这将是一个简短的问题。我有一个按日期排序的ArrayList,当然我看到它有效,但我也想为它写一个测试。
我想检查列表中的下一个值(日期)是否低于上一个值( 日期)。我能够通过使用一些s并添加临时列表来做到这一点,但我想知道是否有更简单的解决方案。我在hamrest文档中读到,有一些像(hamrest包含)的想法可以迭代对象(列表,地图等),但我仍然不知道下一步该怎么做。for
contains
好吧,我认为这将是一个简短的问题。我有一个按日期排序的ArrayList,当然我看到它有效,但我也想为它写一个测试。
我想检查列表中的下一个值(日期)是否低于上一个值( 日期)。我能够通过使用一些s并添加临时列表来做到这一点,但我想知道是否有更简单的解决方案。我在hamrest文档中读到,有一些像(hamrest包含)的想法可以迭代对象(列表,地图等),但我仍然不知道下一步该怎么做。for
contains
[第一个选项]:你可以写自己的匹配器。类似的东西(免责声明:这只是一个示例代码,它没有经过测试,可能并不完美):
@Test
public void theArrayIsInDescendingOrder() throws Exception
{
List<Integer> orderedList = new ArrayList<Integer>();
orderedList.add(10);
orderedList.add(5);
orderedList.add(1);
assertThat(orderedList, isInDescendingOrdering());
}
private Matcher<? super List<Integer>> isInDescendingOrdering()
{
return new TypeSafeMatcher<List<Integer>>()
{
@Override
public void describeTo (Description description)
{
description.appendText("describe the error has you like more");
}
@Override
protected boolean matchesSafely (List<Integer> item)
{
for(int i = 0 ; i < item.size() -1; i++) {
if(item.get(i) <= item.get(i+1)) return false;
}
return true;
}
};
}
此示例使用 s,但您可以轻松地使用 s 进行操作。Integer
Date
[第二个选项],基于OP问题中的引用:您可以创建第二个列表,对原始列表进行排序,而不是使用.通过这种方式,可以更精确地描述最终错误,因为如果元素不在预期顺序中,则会指出该元素。例如,此代码contains
assertThat(origin, contains(ordered))
@Test
public void testName() throws Exception
{
List<Integer> actual = new ArrayList<Integer>();
actual.add(1);
actual.add(5);
actual.add(3);
List<Integer> expected = new ArrayList<Integer>(actual);
Collections.sort(expected);
assertThat(actual, contains(expected.toArray()));
}
将生成描述
java.lang.AssertionError:
Expected: iterable containing [<1>, <3>, <5>]
but: item 1: was <5>
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.junit.Assert.assertThat(Assert.java:865)
at org.junit.Assert.assertThat(Assert.java:832)
...
有一个对这种匹配器的开放请求,但不幸的是,它尚未实现。
我会选择更简单的东西 - 复制列表,对其进行排序,并与原始列表进行比较:
@Test
public void testListOrder() {
ArrayList<SomeObject> original = ...;
ArrayList<SomeObject> sorted = new ArrayList<SomeObject>(original);
Collections.sort(sorted);
Assert.assertEquals ("List is not sorted", sorted, original);
}
编辑:
@dsncode在评论中有一个很好的观点 - 虽然(相对)优雅,但该解决方案在设计时没有考虑任何性能。如果列表不是太大,它应该是可以的,但是如果列表很大,则对其进行排序可能会很昂贵。如果列表很大,则最好直接循环访问它,如果遇到比前一个元素小的元素,则测试失败。例如:
assertTrue(() -> {
Iterator<SomeClass> iter = list.iterator();
SomeClass prev = null;
if (iter.hasNext()) {
prev = iter.next();
}
SomeClass curr = null;
while (iter.hasNext()) {
curr = iter.next();
if (curr.compareTo(prev) < 0) {
return false;
}
prev = curr;
}
return true;
});