简体   繁体   English

通过mockito创建一个模拟列表

[英]Create a mocked list by mockito

I want to create a mocked list to test below code: 我想创建一个模拟列表来测试下面的代码:

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

Here is my implementation: 这是我的实现:

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;
}

But when the test run it throw exception at line: 但是当测试运行时,它会在行中抛出异常:

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

for details: 详情:

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!

How can i fix it ? 我该如何解决? Thanks 谢谢

OK, this is a bad thing to be doing. 好的,这是一件坏事。 Don't mock a list; 不要嘲笑一个清单; instead, mock the individual objects inside the list. 相反,模拟列表中的各个对象。 See Mockito: mocking an arraylist that will be looped in a for loop for how to do this. 请参阅Mockito:嘲笑一个arraylist,它将在for循环中循环以获取如何执行此操作。

Also, why are you using PowerMock? 另外,你为什么使用PowerMock? You don't seem to be doing anything that requires PowerMock. 您似乎没有做任何需要PowerMock的事情。

But the real cause of your problem is that you are using when on two different objects, before you complete the stubbing. 但是你的问题的真正原因是,你正在使用when在两个不同的对象,在完成之前存根。 When you call when , and provide the method call that you are trying to stub, then the very next thing you do in either Mockito OR PowerMock is to specify what happens when that method is called - that is, to do the thenReturn part. 当你调用when ,并提供你试图存根的方法调用时,你在Mockito或PowerMock中做的下一件事就是指定在调用该方法时会发生什么 - 也就是说,执行thenReturn部分。 Each call to when must be followed by one and only one call to thenReturn , before you do any more calls to when . 每次调用when必须跟随一次且只有一次调用thenReturn ,然后再调用when You made two calls to when without calling thenReturn - that's your error. 你让两个调用when无需调用thenReturn -这是你的错误。

When dealing with mocking lists and iterating them, I always use something like: 在处理模拟列表并迭代它们时,我总是使用类似的东西:

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

We can mock list properly for foreach loop. 我们可以为foreach循环正确地模拟列表。 Please find below code snippet and explanation. 请在下面找到代码段和说明。

This is my actual class method where I want to create test case by mocking list. 这是我的实际类方法,我想通过模拟列表创建测试用例。 this.nameList is a list object. this.nameList是一个列表对象。

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

The foreach loop internally works on iterator, so here we crated mock of iterator. foreach循环内部在迭代器上工作,所以这里我们创建了iterator的mock。 Mockito framework has facility to return pair of values on particular method call by using Mockito.when().thenReturn() , ie on hasNext() we pass 1st true and on second call false, so that our loop will continue only two times. Mockito框架具有通过使用Mockito.when().thenReturn()返回特定方法调用的值对的功能,即在hasNext()我们传递1st true而在第二次调用false,因此我们的循环将仅继续两次。 On next() we just return actual return value. 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);
    // ...
}

In this way we can avoid sending actual list to test by using mock of list. 通过这种方式我们可以避免使用list的mock来发送实际列表进行测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM