list.stream().forEach(e -> { dbCall.delete(e.Id());});
这段代码会删除列表中的每个元素。
假设列表中有3个元素,如何进行单元测试:
- 调用了3次删除函数。
- 删除函数的调用顺序是否与列表中元素的顺序相同?
list.stream().forEach(e -> { dbCall.delete(e.Id());});
这段代码会删除列表中的每个元素。
假设列表中有3个元素,如何进行单元测试:
InOrder
。DbCall dbCall = mock(DbCall.class);
List<Element> list = Arrays.asList(newElement(1), newElement(2), newElement(3));
runDeleteMethod(list);
InOrder inorder = inOrder(dbCall);
inorder.verify(dbCall).delete(1);
inorder.verify(dbCall).delete(2);
inorder.verify(dbCall).delete(3);
只需验证应该调用的预期时间dbCall.delete()
。
可以是这样的:
Mockito.verify(dbCall, times(3L)).delete(any(String.class));
流可以并行工作,因此您无法验证顺序。您可以通过索引上的verify元素来执行此操作,但将忽略顺序。Mockito只会验证是否使用了调用+值。这对于单元测试已经足够了。
forEach
,因此测试调用是否按顺序完成没有意义。但是,无论如何,您所要求的不是单元测试。您正在尝试验证实现细节。如果该语句执行正确的操作,并且正确的操作是删除指定的三个条目,那就是您应该验证的,谁在乎以什么顺序调用了哪种方法?测试代码是否删除了三个指定的项目的方法,不取决于您是使用循环,list.forEach
还是list.stream().forEach(…)
。 - HolgerforEach
不是'明确无序的';对于顺序流,它保证是有序的,而对于并行流,则是隐式无序的。此外,删除的顺序也可能很重要,例如,如果列表是按数据库强制执行的项目之间的引用关系排序的。这可能有点牵强,也许不是最好的设计,但仍然是可能的。 - daniuList
,并且行为与调用List#forEach
相同,对于它,“操作按迭代顺序执行(如果指定了迭代顺序)”(https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html#forEach-java.util.function.Consumer-)。Brian的陈述是关于一般情况下的`Stream#forEach`调用,例如也适用于从无序`Collection`创建的流。你是对的,“保证”不是真的 - 但JDK从未改变过现有的行为。 - daniu