如何在测试中模拟CloseableIterator?

3
在我的实现中,我通过ElasticsearchTemplate#stream()从ElasticSearch获取数据,该方法返回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()返回的是Iterator<MyClass>,而不是CloseableIterator<MyClass>,我不知道如何进行强制转换或找到解决方法。


很棒的问题! - davidxxx
3个回答

2
Spring 中的 org.springframework.data.util.CloseableIterator.CloseableIterator 和 JDK 中的 java.util.Iterator 接口相似,事实上 CloseableIteratorIterator 的父接口。
这意味着您可以用 CloseableIterator 替换 Iterator,但反过来则不行,这正是您需要的。
虽然您不能在模拟记录中返回 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();
      }
    };
  }
}

啊,我差点就成功了,我已经生成了 CloseableIterator 但不知道如何将其与我的 Iterator 实例链接起来;传递一个迭代器并在 CloseableIterator 中使用它的方法 hasNext()next() 是太棒了,谢谢 :) - Kamil

0

对于正在使用 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() {}
    }

0
@MockK
private lateinit var closeableIterator: CloseableIterator<YourClass>

fun() {
        every { closeableIterator.hasNext() } returnsMany listOf(true, false)
        every { closeableIterator.next() } returnsMany listOf(YourClass())
}

对于另一个对我有效的Kotlin版本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接