你将嘲笑嵌套在嘲笑之中。你正在呼唤getSomeList()
,在你完成嘲笑之前,它会进行一些嘲笑MyMainModel
。 Mockito 不喜欢你这样做。
Replace
@Test
public myTest(){
MyMainModel mainModel = Mockito.mock(MyMainModel.class);
Mockito.when(mainModel.getList()).thenReturn(getSomeList()); --> Line 355
}
with
@Test
public myTest(){
MyMainModel mainModel = Mockito.mock(MyMainModel.class);
List<SomeModel> someModelList = getSomeList();
Mockito.when(mainModel.getList()).thenReturn(someModelList);
}
要理解为什么这会导致问题,您需要了解一些 Mockito 的工作原理,并且还要了解 Java 中表达式和语句的求值顺序。
Mockito 无法读取您的源代码,因此为了弄清楚您要求它做什么,它在很大程度上依赖于静态。当您调用模拟对象上的方法时,Mockito 会在内部调用列表中记录调用的详细信息。这when
方法从列表中读取最后一个调用并将该调用记录在OngoingStubbing
它返回的对象。
The line
Mockito.when(mainModel.getList()).thenReturn(someModelList);
导致与 Mockito 发生以下交互:
- 模拟方法
mainModel.getList()
叫做,
- 静态方法
when
叫做,
- Method
thenReturn
被称为OngoingStubbing
返回的对象when
method.
The thenReturn
然后方法可以指示它通过接收到的模拟OngoingStubbing
方法来处理任何合适的调用getList
返回方法someModelList
.
事实上,由于 Mockito 看不到你的代码,你也可以编写你的模拟,如下所示:
mainModel.getList();
Mockito.when((List<SomeModel>)null).thenReturn(someModelList);
这种风格阅读起来有些不太清晰,特别是在这种情况下null
必须进行强制转换,但它会生成与 Mockito 相同的交互序列,并且将实现与上面的行相同的结果。
然而,该行
Mockito.when(mainModel.getList()).thenReturn(getSomeList());
导致与 Mockito 发生以下交互:
- 模拟方法
mainModel.getList()
叫做,
- 静态方法
when
叫做,
- A new
mock
of SomeModel
已创建(内部getSomeList()
),
- 模拟方法
model.getName()
叫做,
此时 Mockito 感到困惑。它以为你在嘲笑mainModel.getList()
,但现在你告诉它你想嘲笑model.getName()
方法。对于 Mockito,您似乎正在执行以下操作:
when(mainModel.getList());
// ...
when(model.getName()).thenReturn(...);
这看起来很愚蠢Mockito
因为它不能确定你在做什么mainModel.getList()
.
请注意,我们没有到达thenReturn
方法调用,因为 JVM 需要先评估该方法的参数,然后才能调用该方法。在这种情况下,这意味着调用getSomeList()
method.
一般来说,像 Mockito 那样依赖静态是一个糟糕的设计决策,因为它可能导致违反最小惊讶原则的情况。然而,Mockito 的设计确实可以实现清晰且富有表现力的嘲笑,即使有时会让人感到惊讶。
最后,最新版本的 Mockito 在上面的错误消息中添加了一行额外的内容。这条额外的行表明您可能处于与此问题相同的情况:
3:如果完成,您将在“thenReturn”指令之前对另一个模拟的行为进行存根