4

I'm facing a NullPointerException during unit testing, when trying to test and mock a RestHighLevelClient inside an ElasticClient class:

@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);
   }

}

And the test class:

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

@Mock
private RestHighLevelClient restHighLevelClient;


ElasticClient elasticClient;

@Before
public void init(){

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

}

And the NullPointerException is coming from here:

    @Test
    public void whenElasticIsPingable_thenReturnTrue() throws IOException{

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

Here is the stacktrace:

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)
riorio
  • 6,500
  • 7
  • 47
  • 100
  • is this `RestHighLevelClient` Autowired in `ElasticClient` ?, can you show complete class of `ElasticClient` – Ryuzaki L Nov 18 '19 at 13:03
  • @Deadpool no autowire. Added more details to the class – riorio Nov 18 '19 at 13:18
  • [`restHighLevelClient.ping`](https://github.com/elastic/elasticsearch/blob/master/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java#L719) is a `final` method. Did you enable mockito to handle `final` as mentioned in the [docu](https://javadoc.io/static/org.mockito/mockito-core/3.1.0/org/mockito/Mockito.html#39) ? – second Nov 18 '19 at 14:27

3 Answers3

3

The problem is originated from the fact that the ping method in the RestHighLevelClient is final as can't be mocked regularly.

So, I used the help of this example about PowerMock

And in the final result:

@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();
}
riorio
  • 6,500
  • 7
  • 47
  • 100
1

You need to add a mockito extension for mock a finalized object with these steps:

  1. Create a folder called "mockito-extensions" in test resources folder.
  2. Add a file called "org.mockito.plugins.MockMaker" inside the folder.
  3. In that file, write "mock-maker-inline"
Taylan Derinbay
  • 128
  • 3
  • 13
0

Try:

when(restHighLevelClient.ping(eq(RequestOptions.DEFAULT))).thenReturn(true);
double-beep
  • 5,031
  • 17
  • 33
  • 41
Ahmed HENTETI
  • 1,108
  • 8
  • 18
  • With the same stacktrace ? Which `eq` method are you importing ? – Ahmed HENTETI Nov 18 '19 at 12:28
  • The error is a bit different - `You cannot use argument matchers outside of verification or stubbing` and `java.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)` – riorio Nov 18 '19 at 12:47
  • import static org.mockito.Mockito.eq; – riorio Nov 18 '19 at 12:47
  • The import statement is OK. Can you please run your test without the `@SpringBootTest` to see if it is the root cause of this problem (I'm not sûre) – Ahmed HENTETI Nov 18 '19 at 13:08
  • same result when removing the `@SpringBootTest` – riorio Nov 18 '19 at 13:14