【问题标题】:NullPointerException Problem when trying to mock Elastic Search's RestHighLevelClient尝试模拟 Elastic Search 的 RestHighLevelClient 时出现 NullPointerException 问题
【发布时间】:2020-03-13 19:22:08
【问题描述】:

在单元测试期间,我在尝试在 ElasticClient 类中测试和模拟 RestHighLevelClient 时遇到 NullPointerException:

@Configuration
@NoArgsConstructor
public class ElasticClient{

   @Setter
   private RestHighLevelClient restHighLevelClient;

    @PostConstruct
    public void buildRestHighLevelClient(){

        RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(
                "127.0.0.1",
                9200, "http")
        );

        restClientBuilder.setRequestConfigCallback(
                requestConfigBuilder ->
                        requestConfigBuilder
                                .setConnectTimeout(500000)
                                .setSocketTimeout(600000)
                                .setConnectionRequestTimeout(0)
        )
                .setHttpClientConfigCallback(
                        httpClientBuilder ->
                                httpClientBuilder
                                        .setMaxConnPerRoute(2048)
                );

        restHighLevelClient = new RestHighLevelClient(restClientBuilder);
    }

   public boolean isReachable(){
     return restHighLevelClient.ping(RequestOptions.DEFAULT);
   }

}

还有测试类:

@RunWith(MockitoJUnitRunner.class)
@SpringBootTest
public class ElasticClientTest{

@Mock
private RestHighLevelClient restHighLevelClient;


ElasticClient elasticClient;

@Before
public void init(){

    elasticClient = new ElasticClient();
    elasticClient.setRestHighLevelClient(restHighLevelClient);

}

NullPointerException 来自这里:

    @Test
    public void whenElasticIsPingable_thenReturnTrue() throws IOException{

           when(restHighLevelClient.ping(RequestOptions.DEFAULT)).thenReturn(true);
           Assertions.assertThat(elasticClient.isReachable()).isTrue();
    }

这是堆栈跟踪:

java.lang.NullPointerException
at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1764)
at org.elasticsearch.client.RestHighLevelClient.performRequest(RestHighLevelClient.java:1734)
at org.elasticsearch.client.RestHighLevelClient.ping(RestHighLevelClient.java:694)
at com.example.ElasticClientTest.whenElasticIsPingable_thenReturnTrue(ElasticClientTest.java:44)

【问题讨论】:

  • 这是RestHighLevelClientElasticClient 中自动连线吗?,你能显示ElasticClient 的完整类
  • @Deadpool 没有自动装配。为课程添加了更多详细信息
  • restHighLevelClient.ping 是一个final 方法。您是否启用了 mockito 来处理 final 中提到的 docu

标签: java spring spring-boot mockito resthighlevelclient


【解决方案1】:

试试:

when(restHighLevelClient.ping(eq(RequestOptions.DEFAULT))).thenReturn(true);

【讨论】:

  • 具有相同的堆栈跟踪?您要导入哪个eq 方法?
  • 错误有点不同——You cannot use argument matchers outside of verification or stubbingjava.lang.NullPointerException: options cannot be null at java.util.Objects.requireNonNull(Objects.java:228) at org.elasticsearch.client.Request.setOptions(Request.java:126) at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1761) at org.elasticsearch.client.RestHighLevelClient.performRequest(RestHighLevelClient.java:1734) at org.elasticsearch.client.RestHighLevelClient.ping(RestHighLevelClient.java:694)
  • 导入静态 org.mockito.Mockito.eq;
  • 导入语句OK。你能在没有@SpringBootTest 的情况下运行你的测试,看看它是否是这个问题的根本原因(我不sûre)
  • 删除@SpringBootTest时结果相同
【解决方案2】:

问题源于RestHighLevelClient中的ping方法是final,因为不能定期模拟。

所以,我使用了this example 的帮助关于PowerMock

在最终结果中:

@RunWith(PowerMockRunner.class)
@PrepareForTest(RestHighLevelClient.class)
public class ElasticClientTest{

ElasticClient elasticClient;

RestHighLevelClient restHighLevelClient;

@Before
public void init(){

    restHighLevelClient = mock(RestHighLevelClient.class);

    elasticClient = new ElasticClient();
    elasticClient.setRestHighLevelClient(restHighLevelClient);

}


@Test
public void whenElasticIsPingable_thenReturnTrue() throws IOException{

    when(restHighLevelClient.ping(RequestOptions.DEFAULT)).thenReturn(true);

    Assertions.assertThat(elasticClient.isReachable()).isTrue();
}

【讨论】:

    【解决方案3】:

    您需要添加一个 mockito 扩展来模拟最终对象,步骤如下:

    1. 在测试资源中创建一个名为“mockito-extensions”的文件夹 文件夹。
    2. 在里面添加一个名为“org.mockito.plugins.MockMaker”的文件 文件夹。
    3. 在该文件中,写入“mock-maker-inline”

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-16
      • 1970-01-01
      • 2021-02-11
      • 2015-09-04
      • 1970-01-01
      • 2016-04-23
      • 1970-01-01
      • 2023-03-31
      相关资源
      最近更新 更多