Java 通过 mockito 创建一个模拟列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18514033/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Create a mocked list by mockito
提问by Tien Nguyen
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
我该如何解决?谢谢
采纳答案by Dawood ibn Kareem
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 loopfor how to do this.
好吧,这是一件坏事。不要嘲笑列表;相反,模拟列表中的单个对象。请参阅Mockito:模拟将在 for 循环中循环的数组列表以了解如何执行此操作。
Also, why are you using PowerMock? You don't seem to be doing anything that requires PowerMock.
另外,你为什么使用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 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. Each call to when
must be followed by one and only one call to thenReturn
, before you do any more calls to when
. You made two calls to when
without calling thenReturn
- that's your error.
但问题的真正原因是when
在完成存根之前,您正在使用两个不同的对象。当您调用when
,并提供您尝试存根的方法调用时,您在 Mockito 或 PowerMock 中所做的下一件事就是指定调用该方法时会发生什么 - 即完成该thenReturn
部分。每次调用 to 之前when
必须紧跟一个且仅一个调用 to thenReturn
,然后再调用 to when
。你在when
没有打电话的情况下拨打了两次thenReturn
- 那是你的错误。
回答by Ashish Kirpan
We can mock list properly for foreach loop. Please find below code snippet and explanation.
我们可以为 foreach 循环正确模拟列表。请在下面找到代码片段和解释。
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.
Mockito framework has facility to return pair of values on particular method call by using Mockito.when().thenReturn()
, i.e. on hasNext()
we pass 1st true and on second call false, so that our loop will continue only two times. On next()
we just return actual return value.
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);
// ...
}
In this way we can avoid sending actual list to test by using mock of list.
通过这种方式,我们可以避免使用列表模拟发送实际列表进行测试。
回答by lyuboe
When dealing with mocking lists and iterating them, I always use something like:
在处理模拟列表并迭代它们时,我总是使用类似的东西:
@Spy
private List<Object> parts = new ArrayList<>();