Java assertThat - hamcrest - 检查列表是否已排序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19815004/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
assertThat - hamcrest - check if list is sorted
提问by lukaszrys
Ok I think its going to be a short question. I have an ArrayList that I sorted by date, of course I see it works but I would also like to write a test for it.
好的,我认为这将是一个简短的问题。我有一个按日期排序的 ArrayList,当然我认为它有效,但我也想为它编写一个测试。
I want to check if next value (date) in my list is lower then previous one. I am able to do that with using some for
s and adding temp list, but I'm wondering if there's a easier solution. I read in hamrest documentation that there's somethink like contains
(hamrest contains) that iterate through an object (list,map etc) but still I have no idea what to do next.
我想检查列表中的下一个值(日期)是否低于前一个值。我可以通过使用一些for
s 并添加临时列表来做到这一点,但我想知道是否有更简单的解决方案。我在 hamrest 文档中读到有一些contains
想法(如(hamrest contains))遍历对象(列表、地图等),但我仍然不知道下一步要做什么。
采纳答案by ThanksForAllTheFish
[First Option]: you can write your own Matcher. Something like (disclaimer: this is just a sample code, it is not tested and may be not perfect):
[第一个选项]:您可以编写自己的匹配器。类似于(免责声明:这只是一个示例代码,未经测试,可能并不完美):
@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;
}
};
}
This example is with Integer
s but you can do it with Date
s easily.
这个例子是用Integer
s 但你可以Date
很容易地用s来完成。
[Second option], based on the reference to contains
in the OP's question: you can create a second list, ordering the original one, than using assertThat(origin, contains(ordered))
. This way the eventual error is more precisely described since, if an element is not in the expected order, it will be pointed out. For example, this code
[第二个选项],基于contains
OP 问题中的参考:您可以创建第二个列表,对原始列表进行排序,而不是使用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()));
}
will generate the description
将生成描述
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)
...
回答by Mureinik
There's an open request for such a matcher, but unfortunately it isn't implemented yet.
有这样一个 matcher的公开请求,但不幸的是它还没有实现。
I'd go for something much simpler - copy the list, sort it, and compare to the original:
我会选择更简单的东西 - 复制列表,对其进行排序,然后与原始列表进行比较:
@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);
}
EDIT:
@dsncode has a good point in the comments - while (relatively) elegant, this solution is not designed with any performance consideration. If the list isn't too large it should be OK, but if the list is large, sorting it may be costly. If the list is large, it may be a good idea to iterate over it directly, and fail the test if you encounter an element that is smaller than the previous one. E.g.:
编辑:
@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;
});
回答by Areo
For small collections I suggest to provide expected collection hardcoded in code.
This is unit test and should not contains any logic.
After that you can compare two collections. ( use hamcrest
to check equivalent)
对于小型集合,我建议提供在代码中硬编码的预期集合。这是单元测试,不应包含任何逻辑。之后,您可以比较两个集合。(用于hamcrest
检查等效项)
回答by Zhenya
I had a similar problem, I just check if the next date value in milliseconds is bigger/smaller then the previous one in that list.
我有一个类似的问题,我只是检查下一个以毫秒为单位的日期值是否大于/小于该列表中的前一个。
/**
* Test sort by date
*/
@Test
public void findAllMessagesSortByDate() {
Collection<Message> messages = messageService.getAllMessagesSortedByDate();
long previousTime = messages.iterator().next().getDate().getTimeInMillis();
for (Message message : messages) {
assertTrue(message.getDate.getTimeInMillis() <= previousTime);
previousTime = message.getMessageFolderTs().getTimeInMillis();
}
}
回答by nndru
You can check my answer in another topic, but approach stays same - you should check if items are in expected order.
您可以在另一个主题中查看我的答案,但方法保持不变 - 您应该检查项目是否按预期顺序排列。
How to check if collection contains items in given order using Hamcrest
如何使用 Hamcrest 检查集合是否包含按给定顺序的项目
This approach expects 'Hamcrest' library to be used.
这种方法需要使用“Hamcrest”库。
Hope this helps.
希望这可以帮助。
回答by Alexey Alexeenka
Also it's possible to check it using GUAVA:
也可以使用 GUAVA 来检查它:
import com.google.common.collect.Ordering;
...
...
assertTrue(Ordering.natural().isOrdered(list));
More information here: How to determine if a List is sorted in Java?
此处的更多信息:如何确定列表是否在 Java 中排序?