【问题标题】:How to mock CloseableIterator in a test?如何在测试中模拟 CloseableIterator?
【发布时间】:2020-12-20 14:17:17
【问题描述】:

在我的实现中,我通过 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&lt;MyClass&gt; 不是CloseableIterator&lt;MyClass&gt;,我不知道如何转换它或找到解决方法。

【问题讨论】:

  • 好问题!

标签: java spring elasticsearch mockito


【解决方案1】:

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() 非常棒,谢谢 :)
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2020-07-17
    • 2023-03-20
    • 2017-05-16
    • 1970-01-01
    • 2017-06-14
    • 2017-04-19
    • 2020-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多