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

Java Mockito-存根由模拟对象方法返回的对象的方法,java,mockito,method-chaining,stubbing,Java,Mockito,Method Chaining,Stubbing,假设我有一个模拟对象,我不想存根它的任何方法,但我想存根它返回的对象的方法。比如说, when(mockObject.method1()).thenReturn(returnValue) 通常是这样做的但我想 when(mockObject.method1().method2()).thenReturn(returnValue) 可能吗?如果我这样做,我会得到一个NullPointerException。目前,我使用stub作为返回模拟对象的第一个方法,然后使用返回的模拟对象作为第二个方法的

假设我有一个模拟对象,我不想存根它的任何方法,但我想存根它返回的对象的方法。比如说,

when(mockObject.method1()).thenReturn(returnValue)
通常是这样做的但我想

when(mockObject.method1().method2()).thenReturn(returnValue)
可能吗?如果我这样做,我会得到一个NullPointerException。目前,我使用stub作为返回模拟对象的第一个方法,然后使用返回的模拟对象作为第二个方法的stub。然而,这些临时的模拟对象对我来说是无用的,在将许多方法链接在一起之后,会产生很多无用的模拟对象

编辑:事实上,链接是可行的,但是我的对象导致了NPE。此代码(第一行)导致NPE:

when(graphDb.index().getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);
但这个代码是有效的:

IndexManager indexManager = mock(IndexManager.class);
when(graphDb.index()).thenReturn(indexManager);
when(indexManager.getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);
因此,链接不适用于返回AutoIndexer对象的getNodeAutoIndexer(),而适用于返回RelationshipAutoIndexer对象的getRelationshipAutoIndexer()。两个返回值模拟如下:

nodeAutoIndexer = (AutoIndexer<Node>) mock(AutoIndexer.class);
relAutoIndexer = mock(RelationshipAutoIndexer.class);
nodeAutoIndexer=(AutoIndexer)mock(AutoIndexer.class);
RelationIndexer=mock(RelationshipAutoIndexer.class);

那么是什么导致了问题呢?

根本没有问题

让我们检查以下4行代码:

IndexManager indexManager = mock(IndexManager.class);
when(graphDb.index()).thenReturn(indexManager);
when(indexManager.getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);
第一行创建一个模拟indexManager

第二个命令告诉mock graphDb在调用index方法时返回indexManager(在第一行创建的mock)

第三个命令告诉mock indexManager(在第一行创建)在调用其getNodeOutIndexer方法时返回NodeOutIndexer

最后一行调用graphDb.index(),它返回mock indexManager(您在第二行告诉它这样做),并在调用它的getRelationshipAutoIndexer方法时,要求这个indexManager(它是您在第一行创建的mock)返回RelationIndexer


最后一行之所以有效,是因为您告诉模拟graphDb在调用其索引方法时要返回什么。如果您以前没有这样做,mock graphDb.index()方法将返回null,您将得到一个NPE。

谢谢。假设我有一个很长的函数链,我需要重复这个过程来删除每个函数吗?如果没有stubing index(),就无法获得让NPE工作的代码?我觉得Mockito应该根据函数的返回类型自动地使用mock对象来存根这些方法,这样我就不必麻烦直接存根我不需要的函数了。我只需要这些函数就可以访问其他函数…不。对于返回对象的方法,默认返回值为null。IMHO,你遇到的问题表明你违反了德米特定律:不要与陌生人交谈。请注意,mockito提供了一个深存根特性(
mock(LegacyType.class,RETURNS\u deep\u STUBS)
),但不鼓励使用它,因为你可能会违反良好的设计规则,如德米特定律。还请注意,此功能还不能用于泛型类型,例如列表。谢谢Brice。我不知道,这实际上可以解决OP的问题。