Ответ 1
Ты гнездился в насмешливости. Вы вызываете getSomeList()
, что немного насмехается, прежде чем вы закончите насмешку над MyMainModel
. Mockito не нравится, когда вы это делаете.
Заменить
@Test
public myTest(){
MyMainModel mainModel = Mockito.mock(MyMainModel.class);
Mockito.when(mainModel.getList()).thenReturn(getSomeList()); --> Line 355
}
с
@Test
public myTest(){
MyMainModel mainModel = Mockito.mock(MyMainModel.class);
List<SomeModel> someModelList = getSomeList();
Mockito.when(mainModel.getList()).thenReturn(someModelList);
}
Чтобы понять, почему это вызывает проблему, вам нужно немного узнать о том, как работает Mockito, а также знать, в каком порядке выражаются выражения и выражения в Java.
Mockito не может прочитать ваш исходный код, поэтому, чтобы выяснить, что вы просите его сделать, он много полагается на статическое состояние. Когда вы вызываете метод на макет объекта, Mockito записывает детали вызова во внутренний список вызовов. Метод when
считывает последнюю из этих выписок из списка и записывает этот вызов в возвращаемом объекте OngoingStubbing
.
Линия
Mockito.when(mainModel.getList()).thenReturn(someModelList);
вызывает следующие взаимодействия с Mockito:
- Вызывается метод mock
mainModel.getList()
, - Вызывается статический метод
when
, - Метод
thenReturn
вызывается в объектеOngoingStubbing
, возвращаемом методомwhen
.
Метод thenReturn
может затем проинструктировать макет, полученный им с помощью метода OngoingStubbing
, для обработки любого подходящего вызова методу getList
для возврата someModelList
.
Фактически, поскольку Mockito не может видеть ваш код, вы также можете написать свое издевательство следующим образом:
mainModel.getList();
Mockito.when((List<SomeModel>)null).thenReturn(someModelList);
Этот стиль несколько менее понятен для чтения, тем более, что в этом случае null
должен быть запущен, но он генерирует ту же последовательность взаимодействий с Mockito и достигнет того же результата, что и строка выше.
Однако линия
Mockito.when(mainModel.getList()).thenReturn(getSomeList());
вызывает следующие взаимодействия с Mockito:
- Вызывается метод mock
mainModel.getList()
, - Вызывается статический метод
when
, - Создается новый
mock
ofSomeModel
(внутриgetSomeList()
), - Вызывается метод mock
model.getName()
,
В этот момент Mockito запутался. Он думал, что вы насмехаетесь mainModel.getList()
, но теперь вы говорите, что хотите издеваться над методом model.getName()
. Для Mockito похоже, что вы делаете следующее:
when(mainModel.getList());
// ...
when(model.getName()).thenReturn(...);
Это выглядит глупо для Mockito
, поскольку он не может быть уверен, что вы делаете с mainModel.getList()
.
Обратите внимание, что мы не получили вызов метода thenReturn
, так как JVM должен оценить параметры этого метода, прежде чем он сможет вызвать метод. В этом случае это означает вызов метода getSomeList()
.
Как правило, это плохое дизайнерское решение полагаться на статическое состояние, как это делает Мокито, потому что это может привести к тому, что нарушается Принцип наименьшего удивления. Однако дизайн Mockito делает четкое и выразительное издевательство, даже если это иногда приводит к изумлению.
Наконец, последние версии Mockito добавляют дополнительную строку к сообщению об ошибке выше. Эта дополнительная строка указывает, что вы можете быть в той же ситуации, что и этот вопрос:
3: вы завершаете поведение другого макета внутри перед командой "thenReturn", если завершено