2014-11-13 2 views
2

This code from the documentation полностью озадачивает меня:Как шпион разведывает шпионаж Mockito?

List list = new LinkedList(); 
List spy = spy(list); 

when(spy.size()).thenReturn(100); // <--- how does this spy know 
// not to call the real method???? 

//using the spy calls *real* methods 
spy.add("one"); 
spy.add("two"); 

я получаю его, Mockito странно и вряд ли до сих пор в Java. Непонятная вещь spy.* должна оценить полностью, прежде чем она узнает, что она обернута в when() или что-то в этом роде. Как бы первый метод spy.* не вызывал реальный объект, а более поздние?

+0

Он был дан ответ, прежде чем Пожалуйста, смотрите Http: // StackOverflow. com/questions/11620103/mockito-try-to-spy-on-method-is-call-the-original-method – nadirsaghar

+0

@nadirsaghar Я не вижу, как ответ, на который вы ссылались, отвечает на этот вопрос. –

ответ

1

Я не знаю точную реализацию, но я могу предположить.

Звонок spy(...) сначала проксирует данный объект и сохраняет его в качестве ссылки на вызовы делегатов.

Вызов

when(spy.size()).thenReturn(100); 

практически эквивалентна

Integer result = spy.size(); 
OngoingStubbing<Integer> stubbing = when(result); // result is useless 
stubbing.thenReturn(100); 

Первый вызов size() вызывается на прокси-сервер. Внутри он может зарегистрировать вызов, нажав его, например, на стек(глобальный) Mockito. Когда вы затем вызываете when(), Mockito выталкивает из стека, распознает вызов size() так, как это требуется, и выполняет любую логику, необходимую для этого.

Это может объяснить, почему stubbing in a multithreaded environment - это плохой бизнес.

+2

@DavidWallace You ' я собираюсь заставить меня взглянуть на источник, не так ли? –

+0

Ну, я думал о том, чтобы пойти и посмотреть на источник сам, просто чтобы напомнить себе, но вы на самом деле очень близки. , а окуняющий вызов регистрируется самим шпионом. все остальные детали верны. Я думаю, что я слишком поспешно запустил тебя, и теперь я сниму свой нижний план. –

+0

Хм, пришлось сделать незначительное изменение, чтобы удалить мой нижний план. Иногда я ненавижу этот сайт. –

2

Согласно документации первый when(spy.size()).thenReturn(100) будет на самом деле вызвать реальный List.size() метод, см: http://mockito.github.io/mockito/docs/current/org/mockito/Mockito.html#13

Каждый последующий вызов, конечно, будет затем вернуть высмеивал результат.

Если вы не хотите, реальный метод можно назвать (например when(spy.get(0)).thenReturn(...), вероятно, бросить IndexOutOfBoundsException, вы должны использовать этот шаблон:. doReturn(...).when(spy).get(0);

+0

Это правда. И я сторонник всегда использования 'doReturn (...). Когда (...)' вместо того, чтобы беспокоиться о том, когда вам нужно 'doReturn (...). When (...)', и когда все в порядке, используйте 'when (...). thenReturn (...)'. На самом деле, я опубликовал ответы Mockito на этом сайте, в котором я рекомендую не использовать 'when (...). ThenReturn (...)' вообще. –

+0

@DavidWallace вы имеете в виду, что вы рекомендуете всегда использовать doReturn() при использовании шпионов или всегда использовать его, даже с помощью mocks? Я, как правило, всегда использую его со шпионами, но нахожу классический вэнь (...), затем ... более читаемым и, таким образом, использую это для насмешек. –

+1

Мое предпочтение - использовать его даже с издевательствами.Нет смысла изучать два синтаксиса, когда только один будет охватывать каждый случай. И трудно запомнить все случаи, когда 'when/thenReturn' не будет работать. @JBNizet –

Смежные вопросы