如何在测试中模拟 CloseableIterator?
How to mock CloseableIterator in a test?
在我的实现中,我通过 ElasticsearchTemplate#stream() returns CloseableIterator<>
.
从 ElasticSearch 获取数据
我想通过以下方式模拟此方法:
List<MyClass> foo = new ArrayList<>(); // and then I add some elements
when(mockTemplate.stream(any(SearchQuery.class), eq(MyClass.class))
.thenReturn(foo.iterator());
但 iterator()
returns Iterator<MyClass>
不是 CloseableIterator<MyClass>
我不知道如何转换它或找到解决方法。
来自 Spring 的 org.springframework.data.util.CloseableIterator.CloseableIterator
和来自 JDK 的 java.util.Iterator
是足够接近的接口:实际上 CloseableIterator
有 Iterator
作为父接口。
这意味着您可以将 Iterator
替换为 CloseableIterator
但不能反过来:您需要什么。
虽然您不能在模拟记录中 return Iterator
,但您仍然可以将 Iterator
转换为 CloseableIterator
。由于方法委托,这不是很难,但它仍然需要少量样板文件。
示例:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.util.CloseableIterator;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@ExtendWith(MockitoExtension.class)
public class MockCloseableIteratorTest {
@Mock
ElasticsearchTemplate mockTemplateMock;
@Test
void foo() {
List<String> foo = new ArrayList<>();
// and then I add some elements
Mockito.when(mockTemplateMock.stream(any(SearchQuery.class), eq(String.class)))
.thenReturn(createCloseableIterator(foo.iterator()));
}
private <T> CloseableIterator<T> createCloseableIterator(Iterator<T> iterator) {
return new CloseableIterator<T>() {
@Override public void close() {
}
@Override public boolean hasNext() {
return iterator.hasNext();
}
@Override public T next() {
return iterator.next();
}
};
}
}
对于那些使用 Kotlin 的人来说,以下是 createCloseableIterator 方法的语法:
private fun <T> createCloseableIterator(iterator: Iterator<T>): CloseableIterator<T>? =
object : CloseableIterator<T> {
override fun close() {}
override fun hasNext() = iterator.hasNext()
override fun next() = iterator.next()
override fun remove() {}
}
在我的实现中,我通过 ElasticsearchTemplate#stream() returns CloseableIterator<>
.
我想通过以下方式模拟此方法:
List<MyClass> foo = new ArrayList<>(); // and then I add some elements
when(mockTemplate.stream(any(SearchQuery.class), eq(MyClass.class))
.thenReturn(foo.iterator());
但 iterator()
returns Iterator<MyClass>
不是 CloseableIterator<MyClass>
我不知道如何转换它或找到解决方法。
org.springframework.data.util.CloseableIterator.CloseableIterator
和来自 JDK 的 java.util.Iterator
是足够接近的接口:实际上 CloseableIterator
有 Iterator
作为父接口。
这意味着您可以将 Iterator
替换为 CloseableIterator
但不能反过来:您需要什么。
虽然您不能在模拟记录中 return Iterator
,但您仍然可以将 Iterator
转换为 CloseableIterator
。由于方法委托,这不是很难,但它仍然需要少量样板文件。
示例:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.util.CloseableIterator;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@ExtendWith(MockitoExtension.class)
public class MockCloseableIteratorTest {
@Mock
ElasticsearchTemplate mockTemplateMock;
@Test
void foo() {
List<String> foo = new ArrayList<>();
// and then I add some elements
Mockito.when(mockTemplateMock.stream(any(SearchQuery.class), eq(String.class)))
.thenReturn(createCloseableIterator(foo.iterator()));
}
private <T> CloseableIterator<T> createCloseableIterator(Iterator<T> iterator) {
return new CloseableIterator<T>() {
@Override public void close() {
}
@Override public boolean hasNext() {
return iterator.hasNext();
}
@Override public T next() {
return iterator.next();
}
};
}
}
对于那些使用 Kotlin 的人来说,以下是 createCloseableIterator 方法的语法:
private fun <T> createCloseableIterator(iterator: Iterator<T>): CloseableIterator<T>? =
object : CloseableIterator<T> {
override fun close() {}
override fun hasNext() = iterator.hasNext()
override fun next() = iterator.next()
override fun remove() {}
}