38

我想创建一个模拟列表来测试下面的代码:

 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!

我该如何解决?谢谢

4

3 回答 3

44

好吧,这是一件坏事。不要模拟列表;相反,模拟列表中的各个对象。请参阅Mockito:模拟将在 for 循环中循环的数组列表以了解如何执行此操作。

另外,您为什么要使用 PowerMock?您似乎没有做任何需要 PowerMock 的事情。

when但问题的真正原因是在完成存根之前您正在使用两个不同的对象。当您调用when并提供您尝试存根的方法调用时,您在 Mockito 或 PowerMock 中所做的下一件事就是指定调用该方法时会发生什么 - 即完成thenReturn部分。在您再调用 to 之前,每次调用 towhen之后都必须有一个且只有一个调用to 。你打了两次电话没有打电话- 那是你的错误。thenReturnwhenwhenthenReturn

于 2013-08-29T18:00:12.203 回答
13

在处理模拟列表并对其进行迭代时,我总是使用类似的东西:

@Spy
private List<Object> parts = new ArrayList<>();
于 2016-04-07T15:52:13.963 回答
6

我们可以为 foreach 循环正确地模拟列表。请在下面找到代码片段和解释。

这是我想通过模拟列表创建测试用例的实际类方法。 this.nameList是一个列表对象。

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

foreach 循环内部在迭代器上工作,所以在这里我们创建了迭代器的模拟。Mockito 框架可以通过 using 返回特定方法调用的一对值Mockito.when().thenReturn(),即在hasNext()我们传递第一次 true 和第二次调用 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);
    // ...
}

通过这种方式,我们可以避免使用列表模拟发送实际列表进行测试。

于 2015-05-12T09:13:00.493 回答