Mockito - 存储由模拟对象方法返回的对象的方法

gsi*_*011 12 java mockito method-chaining stubbing

假设我有一个模拟对象,我不想存根任何方法,但是我想要存根它返回的对象的方法.例如,

when(mockObject.method1()).thenReturn(returnValue)
Run Code Online (Sandbox Code Playgroud)

它是如何正常完成的,但我正在寻找,

when(mockObject.method1().method2()).thenReturn(returnValue)
Run Code Online (Sandbox Code Playgroud)

那可能吗?如果我这样做,我会得到一个NullPointerException.目前我有第一个返回模拟对象的方法,然后使用返回的模拟对象,存根第二个方法.但是,这些临时模拟对象对我来说是无用的,并且在将许多方法链接在一起之后,会导致很多无用的模拟对象.

编辑:实际上,链接可能有效,但我的对象正在引起NPE.这段代码(第一行)导致NPE:

when(graphDb.index().getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);
Run Code Online (Sandbox Code Playgroud)

但是这段代码有效:

IndexManager indexManager = mock(IndexManager.class);
when(graphDb.index()).thenReturn(indexManager);
when(indexManager.getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);
Run Code Online (Sandbox Code Playgroud)

所以链接不适用于getNodeAutoIndexer(),它返回一个AutoIndexer对象,同时它对getRelationshipAutoIndexer()有效,返回一个RelationshipAutoIndexer.两个返回值都被模拟如下:

nodeAutoIndexer = (AutoIndexer<Node>) mock(AutoIndexer.class);
relAutoIndexer = mock(RelationshipAutoIndexer.class);
Run Code Online (Sandbox Code Playgroud)

那么可能导致问题的原因是什么?

JB *_*zet 15

完全没有问题.

我们来看看这4行代码:

IndexManager indexManager = mock(IndexManager.class);
when(graphDb.index()).thenReturn(indexManager);
when(indexManager.getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);
Run Code Online (Sandbox Code Playgroud)

第一行创建一个模拟indexManager.

第二个告诉模拟graphDb在调用索引方法时返回indexManager(在第一行创建的模拟).

第三个是在调用其getNodeAutoIndexer方法时,使用模拟indexManager(在第一行创建)返回nodeAutoIndexer.

最后一行调用graphDb.index(),它返回模拟indexManager(你告诉它在第二行做),并询问这个indexManager(你在第一行创建的模拟)在getRelationshipAutoIndexer方法时返回relAutoIndexer叫做.

最后一行的工作原理只是因为你告诉模拟graphDb在调用索引方法时要返回什么.如果您之前没有这样做过,那么mock graphDb.index()方法将返回null并且您将拥有一个NPE.

  • 请注意,mockito提供了一个深度存根功能(`mock(LegacyType.class,RETURNS_DEEP_STUBS)`),但不鼓励使用它,因为您可能会破坏_good设计法则,例如Demeter法则.请注意,此功能尚不适用于泛型类型,例如List. (4认同)
  • RETURNS_DEEP_STUBS确实解决了这个问题. (2认同)