gsi*_*011 13 java junit verify mockito
我正在验证是否使用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)
Run Code Online (Sandbox Code Playgroud)
它出现在
verify(relAutoIndexer).getAutoIndex();
Run Code Online (Sandbox Code Playgroud)
下面显示的测试类代码.
这是我的代码(我倾向于意外地将事情遗漏.请问我任何你认为我缺少的代码,我会添加它):
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;
}
Run Code Online (Sandbox Code Playgroud)
这是测试类的代码:
@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();
}
Run Code Online (Sandbox Code Playgroud)
Bri*_*ice 25
Mockito,直到版本1.8.5,在多态分派的情况下有一个错误.它已修复,可在1.9.0版的第一个候选版本中找到.见问题200.
那么它是如何在你的代码库中发生的.请注意,您正在嘲笑这两个类
nodeAutoIndexer = (AutoIndexer<Node>) mock(AutoIndexer.class);
relAutoIndexer = mock(RelationshipAutoIndexer.class);
Run Code Online (Sandbox Code Playgroud)
AutoIndexer碰巧是一个通用的父接口,在这个接口中有这个方法 ReadableIndex<T> getAutoIndex().RelationshipAutoIndexer是AutoInexer通用部分固定到的子类型Relationship,并覆盖getAutoIndex()返回协变类型的方法ReadableRelationshipIndex.
请参见AutoIndexer和RelationshipIndexer.
好吧,在你的调用代码中你有这些行:
AutoIndexer<Node> nodeAutoIndexer = this.graphDb.index().getNodeAutoIndexer();
AutoIndexer<Relationship> relAutoIndexer = this.graphDb.index().getRelationshipAutoIndexer();
this.nodeIndex = nodeAutoIndexer.getAutoIndex();
this.relIndex = relAutoIndexer.getAutoIndex();
Run Code Online (Sandbox Code Playgroud)
无论nodeAutoIndex在你的产品代码和模拟nodeAutoIndexer测试中的代码有型的参考AutoIndexer<Node>,所以有关于态分派没有问题.但是relAutoIndex在您的生产代码中,类型引用了代码,AutoIndexer<Relationship>并且relAutoIndexer测试代码中的模拟由类型引用RelationshipAutoIndexer,因此在模拟上注册了错误的调用,然后验证失败.
您的解决方案是升级mockito版本 ; 1.9.0 RC1非常稳定,最终版本应该是你的方式.或者您可以从以下位置迁移引用类型(在生产代码中):
AutoIndexer<Relationship> relAutoIndexer = this.graphDb.index().getRelationshipAutoIndexer();
Run Code Online (Sandbox Code Playgroud)
至 :
RelationshipAutoIndexer relAutoIndexer = this.graphDb.index().getRelationshipAutoIndexer();
Run Code Online (Sandbox Code Playgroud)
其他一些评论.
您实际上不需要在此处编写after方法,因为JUnit会在每个方法运行时创建一个新实例,因此您的方法只会添加将要执行的代码.请注意,这不是TestNG的情况.
您可能希望使用Mockito注释,而不是在before方法中创建模拟.不要忘记跑步者.
例如 :
@RunWith(MockitoJUnitRunner.class)
public class YourTest {
@Mock SomeType someTypeMock;
// ...
}
Run Code Online (Sandbox Code Playgroud)
由于几个原因,存根代码有点难看.
为什么不以更清洁的方式写这个; 例如,indexManager在两种情况下引用:
IndexManager indexManager = mock(IndexManager.class);
when(graphDb.index()).thenReturn(indexManager);
when(indexManager.getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(indexManager.getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);
Run Code Online (Sandbox Code Playgroud)
或者根本不参考它
IndexManager indexManager = mock(IndexManager.class);
when(graphDb.index()).thenReturn(indexManager);
when(graphDb.index().getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);
Run Code Online (Sandbox Code Playgroud)
还有一个返回模拟的模拟通常是设计气味的标志.你违反了得墨忒耳的法则,打破它意味着你将经历艰难的测试,糟糕的可维护性和难以进化.当我说你也可以听到我耳语(没有三段论):它会花费你的钱.不要写遗留代码!如果您正在练习TDD或BDD,您将在设计时为自己的代码识别这些问题,这对于防止这些问题非常有用.
使用静态方法,你可以写这个
GraphDatabaseService graphdb = mock(GraphDatabaseService.class, RETURNS_DEEP_STUBS);
Run Code Online (Sandbox Code Playgroud)
或者使用注释,你可以这样写:
@Mock(answer = RETURNS_DEEP_STUBS) GraphDatabaseService graphdb;
Run Code Online (Sandbox Code Playgroud)
并且存根:
when(graphDb.index().getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
29504 次 |
| 最近记录: |