您知道如何适当地模拟 Elasticsearch Java 客户端吗? 目前在 Java 中模拟以下请求:

SearchResponse response = client.prepareSearch(index)
                .setTypes(type)
                .setFrom(0).setSize(MAX_SIZE)
                .execute()
                .actionGet();
SearchHit[] hits = response.getHits().getHits();

我必须嘲笑:

  • client.prepareSearch
  • 搜索请求构建器:
    • builder.execute
    • builder.setSize
    • builder.setFrom
    • builder.setTypes
  • 搜索响应:
    • action.actionGet
  • 搜索响应:
    • response.getHits
    • searchHits.getHits

所以我的测试看起来像:

SearchHit[] hits = ..........;

SearchHits searchHits = mock(SearchHits.class);
when(searchHits.getHits()).thenReturn(hits);

SearchResponse response = mock(SearchResponse.class);
when(response.getHits()).thenReturn(searchHits);

ListenableActionFuture<SearchResponse> action = mock(ListenableActionFuture.class);
when(action.actionGet()).thenReturn(response);

SearchRequestBuilder builder = mock(SearchRequestBuilder.class);
when(builder.setTypes(anyString())).thenReturn(builder);
when(builder.setFrom(anyInt())).thenReturn(builder);
when(builder.setSize(anyInt())).thenReturn(builder);
when(builder.execute()).thenReturn(action);

when(client.prepareSearch(index)).thenReturn(builder);

丑...所以我想知道是否有更“优雅的方式”来模拟这段代码。

谢谢

#1楼 票数:3

我在模拟构建器时遇到了类似的问题,所以我想我会尝试看看是否有更好的方法。

正如 Spoon 先生所说,如果您一开始就可以避免这样做可能会更好,因为它不是您的代码,并且可以被假定为“正常工作”,但我想无论如何我都会试一试。

通过在 Mockito 中使用“默认答案”,我想出了一种(可能是粗略的)方法。 我还在决定我是否喜欢它。

这是我的建设者...

public class MyBuilder {

    private StringBuilder my;

    public MyBuilder() {
        my = new StringBuilder();
    }

    public MyBuilder name(String name) {
        my.append("[name=").append(name).append("]");
        return this;
    }

    public MyBuilder age(String age) {
        my.append("[age=").append(age).append("]");
        return this;
    }

    public String create() {
        return my.toString();
    }
}

(很基本的吧?)

我的测试看起来像这样......

// Create a "BuilderMocker" (any better name suggestions welcome!) 
BuilderMocker<MyBuilder> mocker = BuilderMocker.forClass(MyBuilder.class);
// Get the actual mock builder
MyBuilder builder = mocker.build();

// expect this chain of method calls...
mocker.expect().name("[NAME]").age("[AGE]");

// expect this end-of-chain method call...
Mockito.when(builder.create()).thenReturn("[ARGH!]");

现在,如果我执行以下操作...

System.out.println(builder.name("[NAME]").age("[AGE]").create());

...我希望输出“[ARGH!]”。

如果我更改了最后一行...

System.out.println(builder.name("[NOT THIS NAME]").age("[AGE]").create());

...然后我希望它会因 NullPointerException 而中断。

这是实际的“BuilderMocker”...

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;

import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

public class BuilderMocker<T> {

    private Class<T> clazz;
    private T recorder;
    private T mock;

    // Create a BuilderMocker for the class
    public static <T> BuilderMocker<T> forClass(Class<T> clazz) {
        return new BuilderMocker<T>(clazz);
    }

    private BuilderMocker(Class<T> clazz) {
        this.clazz = clazz;
        this.mock = mock(clazz);
        createRecorder();
    }

    // Sets up the "recorder"
    private void createRecorder() {
        recorder = mock(clazz, withSettings().defaultAnswer(new Answer<Object>() {

            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                // If it is a chained method...
                if (invocation.getMethod().getReturnType().equals(clazz)) {
                    // Set expectation on the "real" mock...
                    when(invocation.getMethod().invoke(mock, invocation.getArguments())).thenReturn(mock);
                    return recorder;
                }
                return null;
            }

        }));
    }

    // Use this to "record" the expected method chain
    public T expect() {
        return recorder;
    }

    // Use this to get the "real" mock...
    public T build() {
        return mock;
    }
}

不确定在 Mockito 中是否有“内置”的方式来做到这一点,但这似乎有效。

  ask by Thibaut M. translate from so

未解决问题?本站智能推荐:

1回复

如何在HTTP客户端Apache上编写测试?

我正在尝试为我的服务编写一个测试,以建立与另一个服务的连接,该服务从数据库返回我的项目。 我的问题是我在测试中设置了连接属性并启动了服务。 这怎么可能是假的或类似的东西? 我的启动服务方法: 我的设置测试方法和一种测试方法: 如何正确执行此操作,以免在测试中配置连接?
1回复

模拟java8 stream.map

我正在使用Mockito我该如何模拟stream.map()调用。 我尝试了类似这样的返回空值。 此打印为空。 我正在寻找一种正确的模拟方法,该方法将在输出中返回“ upperCaseStream”。
2回复

Java:可能与Mockito进行模拟测试

我想我没有正确使用verify 。 这是测试: 这是它调用的代码: 失败追踪: 我要验证的调用是几层。 有没有不同的方法来检查这个?
2回复

Java - 使用Mockito进行测试模拟

我对Mockito并不熟悉,但我正在尝试使用模拟来测试模拟的行为,这是类: 以下是测试类: 我想声明GOLDEN_STATE_WARRIORS在概率范围介于0和GOLDEN_STATE_WARRIORS之间时返回 - 但是我的测试代码出现了一个null的断言错误。
1回复

如何在Java 8中模拟YearMonth

我试图用嘲笑模拟YearMonth.class 。 我正在调用getYear和getMonth方法,因此我想控制要测试的方法中使用的值。 但是,我鼓励以下问题。 该测试对模拟具有以下定义 我正在测试的方法具有以下 如何解决该异常以继续与YearMonth.clas
7回复

如何使用 Mockito 在 Java 中模拟 new Date()

我有一个使用当前时间进行计算的函数。 我想用 mockito 来模拟它。 我想测试的类的一个例子: 我想要类似的东西: 可以嘲笑吗? 我不想更改“已测试”代码以进行测试。
1回复

我可以在 java 方法中模拟 rest 调用吗

我有 2 个方法,我想调用第一个公共方法,该方法又将调用一个私有方法,在私有方法中,我想调用外部服务并从那里的 GET 请求中模拟 500 内部服务错误. 我知道如何模拟整个私有方法,但这行不通我想看看当我从外部服务获得 500 回时会发生什么。 这是我正在测试的两种方法的样子..
1回复

如何在使用Mockito和Java的方法中传递模拟参数

我的课如下: 我想通过使用模拟参数(Class1和Class2的对象)调用方法“ method1”来测试Service类。 我不知道如何使用Mockito做到这一点。有人可以帮助我进行初始推送吗?