Mockito — заглушка метода объекта, который был возвращен методом фиктивного объекта

Допустим, у меня есть фиктивный объект, и я не хочу заглушать ни один из его методов, но я хочу заглушить метод объекта, который он возвращает. Например,

when(mockObject.method1()).thenReturn(returnValue)

как это обычно делается, но я ищу,

when(mockObject.method1().method2()).thenReturn(returnValue)

Это возможно? Я получаю исключение NullPointerException, если я это делаю. В настоящее время у меня есть заглушка первого метода для возврата фиктивного объекта, а затем, используя этот возвращенный фиктивный объект, заглушка второго метода. Однако эти временные фиктивные объекты для меня бесполезны, и после объединения множества методов получается множество бесполезных фиктивных объектов.

РЕДАКТИРОВАТЬ: На самом деле возможно, что цепочка работает, но мои объекты вызывают 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);

Таким образом, цепочка не работала для getNodeAutoIndexer(), которая возвращает объект AutoIndexer, в то время как она работала для getRelationshipAutoIndexer(), которая возвращает RelationshipAutoIndexer. Оба возвращаемых значения имитируются следующим образом:

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

Итак, что может быть причиной проблемы?


person gsingh2011    schedule 29.10.2011    source источник


Ответы (1)


Нет никаких проблем.

Давайте рассмотрим эти 4 строки кода:

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

Первая строка создает макет indexManager.

Второй сообщает макету graphDb вернуть indexManager (макет, созданный в первой строке) при вызове метода индекса.

Третий указывает фиктивному indexManager (созданному в первой строке) возвращать nodeAutoIndexer при вызове его метода getNodeAutoIndexer.

И последняя строка вызывает функцию graphDb.index(), которая возвращает фиктивный indexManager (вы сказали ему сделать это во второй строке) и просит этот indexManager (который является фиктивным, который вы создали в первой строке) вернуть relAutoIndexer, когда его метод getRelationshipAutoIndexer называется.

Последняя строка работает только потому, что вы указали макету graphDb, что возвращать при вызове его метода index. Если бы вы не сделали этого раньше, фиктивный метод graphDb.index() вернул бы null, и у вас был бы NPE.

person JB Nizet    schedule 29.10.2011
comment
Спасибо. Итак, допустим, у меня есть длинная цепочка функций, мне придется повторять этот процесс заглушки каждой функции? Нет никакого способа получить код, который дает NPE для работы, без заглушки index()? Я чувствую, что Mockito должен каким-то образом автоматически заглушать эти методы фиктивными объектами на основе возвращаемых типов функций, чтобы мне не приходилось беспокоиться о заглушках функций, которые мне не нужны напрямую. Мне нужны только эти функции, чтобы добраться до других функций... - person gsingh2011; 29.10.2011
comment
Нет. Возвращаемое значение по умолчанию равно null для методов, которые возвращают объекты. ИМХО, проблема, с которой вы столкнулись, является признаком того, что вы нарушаете закон Деметры: не разговаривайте с незнакомцами. - person JB Nizet; 29.10.2011
comment
Обратите внимание, что mockito предлагает функцию глубокой заглушки (mock(LegacyType.class, RETURNS_DEEP_STUBS)), но не рекомендуется ее использовать, поскольку вы можете нарушить законы хорошего дизайна, такие как Закон Деметры. Также обратите внимание, что эта функция пока не работает с универсальными типами, например со списком. - person Brice; 29.10.2011
comment
Спасибо Брайс. Я не знал об этом, и это действительно могло решить проблему ОП. - person JB Nizet; 29.10.2011