Создайте посмеянный список mockito

Я хочу создать посмеянный список для проверки кода ниже:

 for (String history : list) {
        //code here
    }

Вот моя реализация:

public static List<String> createList(List<String> mockedList) {

    List<String> list = mock(List.class);
    Iterator<String> iterHistory = mock(Iterator.class);

    OngoingStubbing<Boolean> osBoolean = when(iterHistory.hasNext());
    OngoingStubbing<String> osHistory = when(iterHistory.next());

    for (String history : mockedList) {

        osBoolean = osBoolean.thenReturn(true);
        osHistory = osHistory.thenReturn(history);
    }
    osBoolean = osBoolean.thenReturn(false);

    when(list.iterator()).thenReturn(iterHistory);

    return list;
}

Но при запуске теста он генерирует исключение в строке:

OngoingStubbing<DyActionHistory> osHistory = when(iterHistory.next());

для деталей:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:
-> at org.powermock.api.mockito.PowerMockito.when(PowerMockito.java:495)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, you naughty developer!

Как я могу это исправить? Благодаря

Ответы

Ответ 1

Хорошо, это плохо. Не издевайтесь над списком; вместо этого издеваются над отдельными объектами внутри списка. См. Mockito: высмеивает arraylist, который будет зациклен в цикле for для того, как это сделать.

Кроме того, почему вы используете PowerMock? Кажется, вы не делаете ничего, что требует PowerMock.

Но реальная причина вашей проблемы заключается в том, что вы используете when на двух разных объектах, прежде чем завершить завершение. Когда вы вызываете when и предоставляете вызов метода, который вы пытаетесь заглушить, то следующая вещь, которую вы делаете в Mockito или PowerMock, заключается в том, чтобы указать, что происходит, когда этот метод вызывается, т.е. Делать thenReturn часть. Каждый вызов when должен сопровождаться одним и только одним вызовом thenReturn, прежде чем вы сделаете больше вызовов when. Вы сделали два вызова when без вызова thenReturn - этой ошибки.

Ответ 2

Когда мы имеем дело с издевательскими списками и итерацией их, я всегда использую что-то вроде:

@Spy
private List<Object> parts = new ArrayList<>();

Ответ 3

Мы можем правильно составить список для цикла foreach. Ниже приведен фрагмент кода и пояснения.

Это мой метод фактического класса, в котором я хочу создать тестовый пример из-за насмешливого списка. this.nameList - это объект списка.

public void setOptions(){
    // ....
    for (String str : this.nameList) {
        str = "-"+str;
    }
    // ....
}

Цикл foreach внутренне работает на итераторе, поэтому здесь мы разбиваем макет итератора. В структуре Mockito есть возможность вернуть пару значений для конкретного вызова метода с помощью Mockito.when().thenReturn(), то есть на hasNext() мы передаем 1-е истинное значение, а во втором - false, чтобы наш цикл продолжался всего два раза. На next() мы возвращаем фактическое возвращаемое значение.

@Test
public void testSetOptions(){
    // ...
    Iterator<SampleFilter> itr = Mockito.mock(Iterator.class);
    Mockito.when(itr.hasNext()).thenReturn(true, false);
    Mockito.when(itr.next()).thenReturn(Mockito.any(String.class);  

    List mockNameList = Mockito.mock(List.class);
    Mockito.when(mockNameList.iterator()).thenReturn(itr);
    // ...
}

Таким образом, мы можем избежать отправки фактического списка для проверки, используя макет списка.