У Mockito до версии 1.8.5 была ошибка в случае полиморфной отправки. Это было исправлено и доступно в первом выпуске кандидата версии 1.9.0. См. выпуск 200 .
Так как же это происходит в вашей кодовой базе? Обратите внимание, что вы издеваетесь над этими двумя классами
nodeAutoIndexer = (AutoIndexer<Node>) mock(AutoIndexer.class);
relAutoIndexer = mock(RelationshipAutoIndexer.class);
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();
Как nodeAutoIndex
в вашем рабочем коде, так и макет nodeAutoIndexer
в вашем тестовом коде имеют ссылку типа AutoIndexer<Node>
, поэтому проблем с полиморфной отправкой нет.
Однако на relAutoIndex
в вашем рабочем коде ссылается тип AutoIndexer<Relationship>
, а на макет relAutoIndexer
в вашем тестовом коде ссылается тип RelationshipAutoIndexer
, поэтому неправильный вызов регистрируется на макете, а затем не проходит проверку.
Ваше решение - либо обновить версию mockito ; 1.9.0 RC1 очень стабилен, и финальный релиз должен быть на вашем пути. Или вы можете перенести ссылочный тип (в вашем производственном коде) из:
AutoIndexer<Relationship> relAutoIndexer = this.graphDb.index().getRelationshipAutoIndexer();
до:
RelationshipAutoIndexer relAutoIndexer = this.graphDb.index().getRelationshipAutoIndexer();
Несколько других замечаний.
На самом деле вам не нужно писать здесь метод after, так как JUnit создает новый экземпляр при каждом запуске метода, поэтому ваш метод просто добавляет код, который будет выполнен в любом случае. Обратите внимание, что это не относится к TestNG.
Вместо создания насмешек в методе before вы можете использовать аннотации Mockito. Не забудь бегуна.
Например:
@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);
Также наличие насмешки, которая возвращает насмешку, обычно является признаком дизайнерского запаха. Вы нарушаете закон Деметры, и нарушение его означает, что вы будете испытывать трудные испытания, плохую ремонтопригодность и сложную эволюцию. Когда я говорю, что вы также слышите, как я шепчу (без силлогизмов): это будет стоить вам денег. Не пишите устаревший код! Если вы практикуете TDD или BDD, вы обнаружите эти проблемы во время разработки для своего собственного кода, что очень хорошо для их предотвращения.
- Однако, если вы имеете дело с устаревшим кодом, вы можете использовать этот синтаксис с глубокими заглушками:
Используя статические методы, вы можете написать это
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);