Search code examples
javaunit-testingelasticsearchjunitmockito

Getting NPE error when trying to mock ElasticClient in Mockito


I am new to Mockito framework, and I am working on writing tests for the class containing ElasticClient. Below is my actual method:

@Service
@Slf4j
public class CreateIndex {

    private final RestHighLevelClient elasticClient;

    @Autowired
    public IndexService(final RestHighLevelClient elasticClient) throws IOException {
        this.elasticClient = elasticClient;
    }

    public boolean createIndex(String id, String index) {
        try {
            IndexRequest request = new IndexRequest(index);
            request.id(id);
            elasticClient.index(request, RequestOptions.DEFAULT);
            return true;
        } catch (IOException e) {
            log.warn(e.getMessage());
        }
        return false;
    }

My test code looks like this:

public class TestCreateIndex {
   CreateIndex createIndex;
    @Mock
    RestHighLevelClient elasticClient;
    @Rule
    public MockitoRule rule = MockitoJUnit.rule();
    @Before
    public void before() throws IOException {
        createIndex = new CreateIndex(elasticClient);
    }

@Test
    public void TestCreateIndex() throws IOException {
            IndexRequest request = new IndexRequest("1");
            request.id("1");
            Mockito.when(elasticClient.index(request,(RequestOptions.DEFAULT))).thenReturn(indexResponse);

    }
}

For the line Mockito.when(elasticClient.index(request,RequestOptions.DEFAULT )).thenReturn(indexResponse);(RequestOptions is some Class), I am getting below error:

java.lang.NullPointerException: Cannot invoke "org.elasticsearch.client.RestClient.performRequest(org.elasticsearch.client.Request)" because "this.client" is null

    at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1514)
    at org.elasticsearch.client.RestHighLevelClient.performRequest(RestHighLevelClient.java:1484)
    at org.elasticsearch.client.RestHighLevelClient.performRequestAndParseEntity(RestHighLevelClient.java:1454)
    at org.elasticsearch.client.RestHighLevelClient.index(RestHighLevelClient.java:871)

Not sure, how to mock elasticClient properly. Please help.


Solution

  • The problem is that the method you are trying to stub is final:

    public final IndexResponse index(IndexRequest indexRequest, 
                                     RequestOptions options) throws IOException
    

    Mockito does not support mocking final methods out of the box, instead it calls the real method, which causes NPE, since private final RestClient client; is not initialized.

    Fortunately, stubbing final methods can be easily added as a configuration option. See Mock Final Classes and Methods with Mockito

    Before Mockito can be used for mocking final classes and methods, it needs to be configured.

    We need to add a text file to the project's src/test/resources/mockito-extensions directory named org.mockito.plugins.MockMaker and add a single line of text:

    mock-maker-inline

    Mockito checks the extensions directory for configuration files when it is loaded. This file enables the mocking of final methods and classes.

    Alternatively, since mockito 2.7.6, you can use mockito-inline artifact (instead of mockito-core) that enables inline mock making