java – Mockito – “想要但不被调用;但是还有其他与这个模拟的交互“错误

前端之家收集整理的这篇文章主要介绍了java – Mockito – “想要但不被调用;但是还有其他与这个模拟的交互“错误前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我验证一个函数是使用Mockito调用的,但是Mockito告诉我,我正在验证的函数从来没有被调用,而其他函数调用.但是在我看来,我正在调用正确的功能

这是我遇到的错误的堆栈跟踪:

@H_502_4@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)

它发生在

@H_502_4@verify(relAutoIndexer).getAutoIndex();

的测试类代码如下所示.

这是我的代码(我有一个倾向,意外的事情,请问我的任何代码,你认为我失踪,我会添加):

@H_502_4@public DataServiceImpl(GraphDatabaseService graphDb) { super(); this.graphDb = graphDb; unarchivedParent = new UnarchivedParent(graphDb.createNode()); archivedParent = new ArchivedParent(graphDb.createNode()); packetParent = new PacketParent(graphDb.createNode()); userParent = new UserParent(graphDb.createNode()); this.initIndices(); } /** * Initializes the node and relationship indexes. * * Updates the set of indexed properties to match {@link DataServiceImpl} * .NODE_KEYS_INDEXABLE and {@link DataServiceImpl}.REL_KEYS_INDEXABLE. * * Note: auto indices can also be configured at database creation time and * just retrieved at runtime. We might want to switch to that later. */ private void initIndices() { /* Get the auto-indexers */ AutoIndexer<Node> nodeAutoIndexer = this.graphDb.index() .getNodeAutoIndexer(); AutoIndexer<Relationship> relAutoIndexer = this.graphDb.index() .getRelationshipAutoIndexer(); this.updateIndexProperties(nodeAutoIndexer,DataServiceImpl.NODE_KEYS_INDEXABLE); this.nodeIndex = nodeAutoIndexer.getAutoIndex(); this.updateIndexProperties(relAutoIndexer,DataServiceImpl.REL_KEYS_INDEXABLE); this.relIndex = relAutoIndexer.getAutoIndex(); } /** * Sets the indexed properties of an {@link AutoIndexer} to the specified * set,removing old properties and adding new ones. * * @param autoIndexer * the AutoIndexer to update. * @param properties * the properties to be indexed. * @return autoIndexer,this given AutoIndexer (useful for chaining calls.) */ private <T extends PropertyContainer> AutoIndexer<T> updateIndexProperties( AutoIndexer<T> autoIndexer,Set<String> properties) { Set<String> indexedProps = autoIndexer.getAutoIndexedProperties(); // Remove unneeded properties. for (String prop : difference(indexedProps,properties)) { autoIndexer.stopAutoIndexingProperty(prop); } // Add new properties. for (String prop : difference(properties,indexedProps)) { autoIndexer.startAutoIndexingProperty(prop); } // Enable the index,if needed. if (!autoIndexer.isEnabled()) { autoIndexer.setEnabled(true); } return autoIndexer; }

这里是测试类的代码

@H_502_4@@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(); }

解决方法

Mockito,直到版本1.8.5,在多态发送的情况下有一个错误.它是固定的,可在版本1.9.0的第一个发行版中.见 issue 200.

那么在代码库中如何发生.注意你在嘲笑这两个类

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

AutoIndexer恰好是一个通用的父接口,在这个接口中有这个方法ReadableIndex< T> getAutoIndex(). RelationshipAutoIndexer是AutoInexer的一个子类型,其中通用部分被修改为Relationship,并覆盖getAutoIndex()方法以返回协变类型ReadableRelationshipIndex.

AutoIndexerRelationshipIndexer.

那么在你的通话代码中,你有以下几行:

@H_502_4@AutoIndexer<Node> nodeAutoIndexer = this.graphDb.index().getNodeAutoIndexer(); AutoIndexer<Relationship> relAutoIndexer = this.graphDb.index().getRelationshipAutoIndexer(); this.nodeIndex = nodeAutoIndexer.getAutoIndex(); this.relIndex = relAutoIndexer.getAutoIndex();

您的生产代码中的nodeAutoIndex和测试代码中的mock nodeAutoIndexer都具有AutoIndexer&Node Node类型的引用,因此关于多态调度没有问题.
但是,您的生产代码中的relAutoIndex由AutoIndexer&Relationships类型引用.并且您的测试代码中的模拟relAutoIndexer由RelationshipAutoIndexer引用,因此错误的调​​用在模拟器上注册,然后验证失败.

您的解决方案是升级mockito版本; 1.9.0 RC1是非常稳定的,最后一个版本应该是你的方式.或者您可以从以下地址迁移参考类型(在生产代码中):

@H_502_4@AutoIndexer<Relationship> relAutoIndexer = this.graphDb.index().getRelationshipAutoIndexer();

至 :

@H_502_4@RelationshipAutoIndexer relAutoIndexer = this.graphDb.index().getRelationshipAutoIndexer();

另外几句话.

>你不需要在这里写一个after方法,因为JUnit在每个方法运行时创建一个新的实例,所以你的方法只是添加将要完成的代码.请注意,TestNG不是这样.
而不是在before方法中创建你的mocks,你可能想使用Mockito注释.不要忘记跑步者.

例如 :

@H_502_4@@RunWith(MockitoJUnitRunner.class) public class YourTest { @Mock SomeType someTypeMock; // ... }

>由于几个原因,stubbing代码有点丑陋.

>你应该写一个一致的存根.

为什么不用清洁的方式写这个;例如在两种情况下引用indexManager:

@H_502_4@IndexManager indexManager = mock(IndexManager.class); when(graphDb.index()).thenReturn(indexManager); when(indexManager.getNodeAutoIndexer()).thenReturn(nodeAutoIndexer); when(indexManager.getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);

或者不要引用它

@H_502_4@IndexManager indexManager = mock(IndexManager.class); when(graphDb.index()).thenReturn(indexManager); when(graphDb.index().getNodeAutoIndexer()).thenReturn(nodeAutoIndexer); when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);

还有一个模仿的模拟通常是设计气味的标志.你打破了德米特的法律,打破这意味着你会遇到困难的测试,可维护性差,难以进化.当我说你可以听到我耳语(没有三段话):它会花费你的钱.不要写遗留代码!如果您正在练习TDD或BDD,那么您将在设计时将自己的代码识别出这些问题,这样可以很好地防止这些问题.

>但是,如果您正在处理旧版代码,则可以使用此深层存根语法:

使用静态方法可以写这个

@H_502_4@GraphDatabaseService graphdb = mock(GraphDatabaseService.class,RETURNS_DEEP_STUBS);

或者使用注释,你可以写这个:

@H_502_4@@Mock(answer = RETURNS_DEEP_STUBS) GraphDatabaseService graphdb;

和桩:

@H_502_4@when(graphDb.index().getNodeAutoIndexer()).thenReturn(nodeAutoIndexer); when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);

猜你在找的Java相关文章