Java Mockito-“;被通缉但未被援引;然而,还有其他与这个模拟的互动;错误

Java Mockito-“;被通缉但未被援引;然而,还有其他与这个模拟的互动;错误,java,junit,mockito,verify,Java,Junit,Mockito,Verify,我正在验证是否使用Mockito调用了一个函数,但Mockito告诉我,我正在验证的函数从未调用过,其他函数也被调用过。但在我看来,我调用了正确的函数 下面是我得到的错误的堆栈跟踪: Wanted but not invoked: relationshipAutoIndexer.getAutoIndex(); -> at org.whispercomm.manes.server.graph.DataServiceImplTest.testInitIndices(DataServiceImp

我正在验证是否使用Mockito调用了一个函数,但Mockito告诉我,我正在验证的函数从未调用过,其他函数也被调用过。但在我看来,我调用了正确的函数

下面是我得到的错误的堆栈跟踪:

Wanted but not invoked:
relationshipAutoIndexer.getAutoIndex();
-> at org.whispercomm.manes.server.graph.DataServiceImplTest.testInitIndices(DataServiceImplTest.java:117)

However, there were other interactions with this mock:
-> at org.whispercomm.manes.server.graph.DataServiceImpl.updateIndexProperties(DataServiceImpl.java:136)
-> at org.whispercomm.manes.server.graph.DataServiceImpl.updateIndexProperties(DataServiceImpl.java:144)
-> at org.whispercomm.manes.server.graph.DataServiceImpl.updateIndexProperties(DataServiceImpl.java:148)
-> at org.whispercomm.manes.server.graph.DataServiceImpl.updateIndexProperties(DataServiceImpl.java:149)
-> at org.whispercomm.manes.server.graph.DataServiceImpl.initIndices(DataServiceImpl.java:121)

    at org.whispercomm.manes.server.graph.DataServiceImplTest.testInitIndices(DataServiceImplTest.java:117)
它发生在

verify(relAutoIndexer).getAutoIndex();
下面所示的测试类代码

这是我的代码(我有一种偶然遗漏的倾向。请向我询问您认为我缺少的任何代码,我会添加它):

公共数据服务MPL(GraphDatabaseService graphDb){ 超级(); this.graphDb=graphDb; unarchivedParent=新的unarchivedParent(graphDb.createNode()); archivedParent=新的archivedParent(graphDb.createNode()); packetParent=newpacketparent(graphDb.createNode()); userParent=newuserparent(graphDb.createNode()); this.initindex(); } /** *初始化节点和关系索引。 * *更新索引属性集以匹配{@link DataServiceImpl} *.NODE_KEYS_可索引和{@link dataservice impl}.REL_KEYS_可索引。 * *注意:自动索引也可以在数据库创建时和 *只是在运行时检索。我们以后可能想换个话题。 */ 私有索引(){ /*获取自动索引器*/ 自动索引器nodeAutoIndexer=this.graphDb.index() .getNodeAutoIndexer(); 自动索引器relAutoIndexer=this.graphDb.index() .getRelationshipAutoIndexer(); 此.updateIndexProperties(节点索引器, DataServiceImpl.NODE_KEYS_INDEXABLE); this.nodeIndex=nodeAutoIndexer.getAutoIndex(); 此.updateIndexProperties(relAutoIndexer, DataServiceImpl.REL_KEYS_INDEXABLE); this.relIndex=relAutoIndexer.getAutoIndex(); } /** *将{@link AutoIndexer}的索引属性设置为指定的 *设置,删除旧属性并添加新属性。 * *@param自动索引器 *要更新的自动索引器。 *@param属性 *要编制索引的属性。 *@return autoIndexer,这是给定的自动索引器(用于链接调用) */ 专用自动索引器UpdateIndexProperty( 自动索引器(自动索引器,设置属性){ Set indexedrops=autoIndexer.getAutoIndexedProperties(); //删除不需要的属性。 for(字符串属性:差异(IndexedOps、属性)){ 自动索引器。停止自动索引属性(prop); } //添加新属性。 for(字符串属性:差异(属性、索引操作)){ startAutoIndexingProperty(prop)自动索引器; } //如果需要,启用索引。 如果(!autoIndexer.isEnabled()){ autoIndexer.setEnabled(真); } 返回自动索引器; } 下面是测试类的代码:

@Before
public void setup() {
   nA = mock(Node.class);
   nB = mock(Node.class);
   packetA = new PacketWrapper(nA);
   packetB = new PacketWrapper(nB);
   RelA = mock(Relationship.class);
   RelB = mock(Relationship.class);
   graphDb = mock(GraphDatabaseService.class);
   nodeAutoIndexer = (AutoIndexer<Node>) mock(AutoIndexer.class);
       relAutoIndexer = mock(RelationshipAutoIndexer.class);
}

@After
public void tearDown() {
  packetA = null;
  packetB = null;
}
/*
 * ---------------- Test initIndices() ---------------
 */
//TODO
@Test
public void testInitIndices() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
   IndexManager indexManager = mock(IndexManager.class);
   when(graphDb.index()).thenReturn(indexManager);
   when(indexManager.getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
       when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);
   dataService = new DataServiceImpl(graphDb);
       verify(nodeAutoIndexer, atLeastOnce()).getAutoIndex();
       verify(relAutoIndexer).getAutoIndex();                       
}
@之前
公共作废设置(){
nA=模拟(Node.class);
nB=模拟(Node.class);
packetA=新的包装纸(nA);
packetB=新的包装纸(nB);
RelA=mock(Relationship.class);
RelB=mock(Relationship.class);
graphDb=mock(GraphDatabaseService.class);
nodeAutoIndexer=(AutoIndexer)mock(AutoIndexer.class);
RelationIndexer=mock(RelationshipAutoIndexer.class);
}
@之后
公共无效拆卸(){
packetA=null;
packetB=null;
}
/*
*--------------测试初始索引()---------------
*/
//待办事项
@试验
public void testinities()引发IllegalArgumentException、IllegalAccessException、InvocationTargetException、NoSuchMethodException{
IndexManager IndexManager=mock(IndexManager.class);
when(graphDb.index())。然后return(indexManager);
当(indexManager.getNodeAutoIndexer())。然后返回(nodeAutoIndexer);
当(graphDb.index().getRelationshipAutoIndexer())。然后返回(RelationIndexer);
dataService=新的DataServiceImpl(graphDb);
验证(nodeAutoIndexer,至少一次()).getAutoIndex();
验证(relAutoIndexer).getAutoIndex();
}

直到1.8.5版,Mockito在多态分派的情况下有一个bug。它已修复,并在1.9.0版的第一个候选发行版中提供。请参阅

那么它是如何在您的代码库中发生的呢。注意,您正在模拟这两个类

nodeAutoIndexer = (AutoIndexer<Node>) mock(AutoIndexer.class);
relAutoIndexer = mock(RelationshipAutoIndexer.class);
生产代码中的
nodeAutoIndex
和测试代码中的mock
nodeAutoIndexer
都有一个类型为
AutoIndexer
的引用,因此多态调度没有问题。 但是,生产代码中的
relAutoIndex
被类型
AutoIndexer
引用,测试代码中的mock
relAutoIndexer
被类型
RelationshipAutoIndexer
引用,因此在mock上注册错误调用,然后验证失败

您的解决方案是升级mockito版本;1.9.0 RC1非常稳定,最终版本应该会按您的方式发布或者您可以从以下位置迁移引用类型(在生产代码中):


还有几句话

  • 实际上,您不需要在这里编写after方法,因为JUnit在每次方法运行时都会创建一个新实例,所以您的方法只需添加无论如何都要完成的代码。注意,TestNG的情况并非如此

  • 您可能希望使用Mockito注释,而不是在before方法中创建mock。别忘了跑步者

例如:

@RunWith(MockitoJUnitRunner.class)
public class YourTest {
    @Mock SomeType someTypeMock;
    // ...
}
  • 存根代码有点难看,原因有几个

    • 你应该写一致的存根
为什么不写得更干净些呢;例如,在两种情况下都引用
indexManager

IndexManager indexManager = mock(IndexManager.class);
when(graphDb.index()).thenReturn(indexManager);
when(indexManager.getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(indexManager.getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);
或者根本不引用它

IndexManager indexManager = mock(IndexManager.class);
when(graphDb.index()).thenReturn(indexManager);
when(graphDb.index().getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);
还有一个mock返回一个mock通常是设计气味的标志。您正在违反德米特定律,违反它意味着您将经历困难的测试、糟糕的可维护性和困难的演变。当我
RelationshipAutoIndexer relAutoIndexer = this.graphDb.index().getRelationshipAutoIndexer();
@RunWith(MockitoJUnitRunner.class)
public class YourTest {
    @Mock SomeType someTypeMock;
    // ...
}
IndexManager indexManager = mock(IndexManager.class);
when(graphDb.index()).thenReturn(indexManager);
when(indexManager.getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(indexManager.getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);
IndexManager indexManager = mock(IndexManager.class);
when(graphDb.index()).thenReturn(indexManager);
when(graphDb.index().getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);
GraphDatabaseService graphdb = mock(GraphDatabaseService.class, RETURNS_DEEP_STUBS);
@Mock(answer = RETURNS_DEEP_STUBS) GraphDatabaseService graphdb;
when(graphDb.index().getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);