我在函数中有一行代码,其对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
,那为什么呢?
答案 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));