如何对Java8流进行单元测试?
如何对Java8流进行单元测试?,java,unit-testing,testing,java-stream,Java,Unit Testing,Testing,Java Stream,list.stream().forEach(e->{dbCall.delete(e.Id());}) 列表中的每个项目都将从数据库中删除 假设列表中有3项,如何进行单元测试: Delete被调用了3次 Delete被称为“按顺序/顺序”,即列表中元素的顺序 您可以按顺序使用JUnit的 DbCall dbCall = mock(DbCall.class); List<Element> list = Arrays.asList(newElement(1), newElement(2),
list.stream().forEach(e->{dbCall.delete(e.Id());})代码>
列表中的每个项目都将从数据库中删除
假设列表中有3项,如何进行单元测试:
Delete被调用了3次
Delete被称为“按顺序/顺序”,即列表中元素的顺序李>
您可以按顺序使用JUnit的
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-DbCall=mock(DbCall.class);
List List=Arrays.asList(新元素(1)、新元素(2)、新元素(3));
运行删除方法(列表);
InOrder InOrder=InOrder(dbCall);
inoder.verify(dbCall).delete(1);
inoder.verify(dbCall).delete(2);
inoder.verify(dbCall).delete(3);
只需验证应该调用的预期时间dbCall.delete()
。
这可以是这样的:
Mockito.verify(dbCall, times(3L)).delete(any(String.class));
流可以并行工作,因此您无法验证序列。您可以使用索引上的verify元素来执行此操作,但该序列将被忽略。Mockito将只验证是否使用了call+值。这对于单元测试来说已经足够了 由于您使用的是显式无序的forEach
,因此测试调用是否按顺序完成没有意义。但无论如何,您要求的不是单元测试。您正在尝试验证实现详细信息。如果语句做了正确的事情,正确的事情是删除指定的三个条目,并且这是您应该验证的,那么谁会关心以什么顺序调用了哪个方法呢?测试代码是否删除三个指定项的方法并不取决于是否使用循环,list.forEach
或list.stream()。forEach(…)
@HolgerforEach
不是“显式无序的”;对于顺序流,它保证是有序的,而对于并行流,它是隐式无序的。此外,删除顺序可能很重要,例如,如果列表是根据数据库强制执行的项之间的引用关系排序的。也许牵强,也许不是最好的设计,但可能。@daniu你是怎么得出这个结论的?报告中明确指出:“此操作的行为显然是不确定的”。关于并行流执行的语句不允许对顺序流得出相反的结论。但是对于单元测试,顺序仍然是不相关的。重要的是,这三项是否被正确删除。@Holger我得出这个结论,因为在本例中,流来自列表
,其行为与调用列表#forEach
,对于该列表,“操作按迭代顺序执行(如果指定了迭代顺序)”()。Brian的陈述是关于Stream#forEach
调用的一般情况,例如也用于从无序的集合创建的流。你是对的,“保证”不是真的——但是JDK从来没有改变过现有的行为。@Holger至于在单元测试中顺序是不相关的,那是不对的。“正确删除三项”是一项操作要求,单元测试(严格意义上)验证技术行为。另外,一般来说,调用顺序在单元测试的范围内:如果这是三个不同的服务调用,而不是db deletes,我相信您会同意顺序可能是相关的,我们不会讨论这个问题。