2

I am currently working on how to test coverage my ElasticSearch Class which implements RestHighLevelClient. The problem is that it returns null pointer pointing to the RestHighLevelClient.class. I am new to ES and I don't know where am I going wrong.

Here is my ElasticSearch class:

@Service
public class ElasticsearchService {

    @Autowired
    private LoggingService loggingService;

    @Autowired
    private LocationService locationService;

    @Autowired
    private RestHighLevelClient client;

    @Autowired
    private ObjectMapper mapper;

    @Autowired
    private Utils util;

    @Autowired
    private ApplicationProperties prop;

    public String addAtmStatusRecord(ATM atm) throws IOException {
        GeoPoint geoPoint = locationService.getLocation(atm.getTerminalId());

        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject()
            .field("terminalId", atm.getTerminalId())
            .field("atmStatus", "D".equals(atm.getAtmStatus()) ? 1 : 0)
            .field("atmLocation", atm.getAtmLocation())
            .field("errorDescription", atm.getErrorDescription())
            .field("lastTranTime", atm.getLastTranTime())
            .field("lastDevStatTime", atm.getLastDevStatTime())
            .field("errorCode", atm.getErrorCode())
            .field("termBrcode", atm.getTermBrcode())
            .timeField("@timestamp", new Date())
            .latlon("location", geoPoint.getLat(), geoPoint.getLon())
            .endObject();

        IndexRequest indexRequest = new IndexRequest(prop.getEsIndex(), prop.getEsType(), atm.getTerminalId()).source(builder);
        IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
        loggingService.log(this.getClass().toString(), atm.getTerminalId(), TraceLog.SUCCESSFUL_PUSH_TO_ELASTIC_SEARCH, 
                util.mapToJsonString(atm));

        return response.getResult().name();
    }



    public List<AtmElasticSearchData> searchForOfflineAtmData() throws IOException {
        SearchResponse searchResponse = getAllOfflineAtmData();
        List<SearchHit> searchHits = Arrays.asList(searchResponse.getHits().getHits());
        List<AtmElasticSearchData> listOfAtm = new ArrayList<>();

        for (SearchHit searchHit : searchHits) {
            listOfAtm.add(mapper.readValue(searchHit.getSourceAsString(), AtmElasticSearchData.class));
        }

        return listOfAtm;
    }

    public SearchResponse getAllOfflineAtmData() throws IOException {
        Map<String, Object> queryParam = new HashMap<>();   
        queryParam.put("atmStatus", 1);
        return retrieveElasticSearchData(queryParam);
    }

    public long getAllOfflineAtmCount() throws IOException {
        return getAllOfflineAtmData().getHits().getTotalHits();
    }

    private SearchResponse retrieveElasticSearchData(Map<String, Object> queryParams) throws IOException {
        SearchSourceBuilder searchSourceBuilder  = new SearchSourceBuilder();

        queryParams.entrySet().forEach(queryParam -> searchSourceBuilder.query(
                QueryBuilders.termQuery(queryParam.getKey(), queryParam.getValue())));
        searchSourceBuilder.from(0);
        searchSourceBuilder.size(Integer.parseInt(prop.getEsMaxSearchSize()));
        SearchRequest searchRequest = new SearchRequest(prop.getEsIndex())
                .types(prop.getEsType())
                .source(searchSourceBuilder);

        return client.search(searchRequest, RequestOptions.DEFAULT);
    }
}

Here is my test case:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = ATMMonitoringApplication.class, initializers = ConfigFileApplicationContextInitializer.class)
public class ElasticsearchServiceTest {

    @Autowired
    private ElasticsearchService elasticsearchService;

    @MockBean
    private LoggingService loggingService;

    @MockBean
    private LocationService locationService;

    @MockBean
    private RestHighLevelClient client;

    @MockBean
    private ObjectMapper mapper;

    @MockBean
    private Utils util;

    @MockBean
    private IndexRequest indexRequest;
    @MockBean IndexResponse indexResponse;

    @Value("${elastic.search.atm.monitoring.index}")
    private String esIndex;

    @Value("${elastic.search.atm.monitoring.type}")
    private String esType;

    private ATM atm;

    @Before
    public void setUp() throws ParseException, IOException {

        client = mock(RestHighLevelClient.class);
        indexRequest = mock(IndexRequest.class);
        indexResponse = mock(IndexResponse.class);

        MockitoAnnotations.initMocks(this);
        atm = new ATM();
        atm.setAtmLocation("location");
        atm.setAtmStatus("U");
        atm.setErrorCode("222");
        atm.setErrorDescription("STATUS");
        atm.setLastDevStatTime(null);
        atm.setLastTranTime(null);
        atm.setTerminalId("123");
        atm.setTermBrcode("111");

    }

    @Test
    public void testAddAtmStatusRecordIsNull() throws IOException, NumberFormatException, IllegalArgumentException, IllegalAccessException {

        Mockito.when(locationService.getLocation(Mockito.anyString())).thenReturn(new GeoPoint(121.00000, 11.9874));
        elasticsearchService.addAtmStatusRecord(atm);
        assertThat(1).isEqualTo(1);
    }
        @Test
    public void testAddAtmStatusRecordAtmIsDown() throws IOException {
        ATM atm = new ATM();
        atm.setAtmStatus("D");
        Mockito.when(locationService.getLocation(Mockito.anyString())).thenReturn(new GeoPoint(121.00000, 11.9874));
        elasticsearchService.addAtmStatusRecord(atm);
        assertThat(1).isEqualTo(1);
    }

    @Test
    public void testGetAllOfflineAtmCount() throws IOException {

        elasticsearchService.getAllOfflineAtmCount();
        assertThat(1).isEqualTo(1);

    }

    @Test
    public void testsearchForOfflineAtmData() throws IOException {

        List<AtmElasticSearchData> atmEsData = new ArrayList<>();
            elasticsearchService.searchForOfflineAtmData();

        assertThat(1).isEqualTo(1);
    }


}

My port is already set on 9200 in my app.properties.

Please send me out some help on this. I really need to resolve this. Any help would be much appreciated.

Smile
  • 3,832
  • 3
  • 25
  • 39
Ronald
  • 37
  • 1
  • 7
  • If you have marked a variable `@MockBean`, why are you again assigning it a mocked object like `client = mock(RestHighLevelClient.class);`? – Smile Feb 19 '20 at 09:27

1 Answers1

1

Most of the methods in RestHighLevelClient are final so cannot be mocked and call actual method and throwing null pointer. Please see this post NullPointerException Problem when trying to mock Elastic Search's RestHighLevelClient

Hars
  • 169
  • 2
  • 12