我应该模拟流操作的列表吗?

时间:2018-10-29 12:25:01

标签: java unit-testing mockito junit4

我在函数中有一行代码,其对ArrayList进行流操作为:

List<Entity> list = xyz(); 

long result = list.stream().map(n -> n.getData()).filter(n -> n == 1).count();

现在,当我为此方法编写测试时,应该这样做:

@Mock
private List<Entity> list;

//inside the test method
when(list.stream().map(any()).filter(any()).count()).thenReturn(someValue);

我想到的是,当我们在代码中调用流操作时,基本上是从类中退出来调用这些函数。由于这是单元测试,因此我们应该保留在模块内部。请澄清一下我是否有误解。如果我们不需要嘲笑List,那为什么呢?

2 个答案:

答案 0 :(得分:3)

可以模拟列表,但这可能比它值得的麻烦更多。列表和流接口是如此之大,以至于很难模拟它们而不要模拟每个方法(不,谢谢)或仅模拟您使用的方法,这意味着您将依赖于了解所使用方法的内部实现细节。重新测试。后者导致脆弱的测试。最好编写一个只关心输入和输出而不关心实现细节的测试。

当难以创建对象的正确版本时,或者当您想为测试提供隔离时,应使用模拟。创建列表并不难,而且经过了充分的测试,以至于对其进行模拟并不能真正为增加隔离度提供任何价值。

只需正常创建列表即可。

list = Arrays.asList(new Entity(1), new Entity(2), new Entity(1));

在这种情况下,您可以断言该方法的结果为2。

您可能会从模拟实体中获得一些收获,例如

Mockito.when(Entity.getData()).thenReturn(1);

答案 1 :(得分:0)

似乎您并不真正在乎该流操作的内部工作,而只是在乎其结果。

在我看来,您应该将该逻辑提取到其他一些特殊的类中,这些类将具有一个公共方法来接受列表并返回计数。

然后,您可以将该类用作依赖项并模拟其count方法:

// the impl

private DataCounter dataCounter;

...

List<Entity> list = xyz(); 

long result = dataCounter.count(list);

// test class

@Mock
private DataCounter dataCounter;

//inside the test method
when(dataCounter.count(Mockito.any(List.class)).thenReturn(Mockito.eq(someValue));