0

I am trying to unit test the java class which uses Jackson to parse the JSON response from rest call and mapping it to the POJO. I can successfully get the response from the rest call. But when I do unit testing using Mockito and Junit, am getting nullpointer exception. Is it possible to unit test ObjectMapper? Whether mockito work with jackson. What exactly i should do make the unit testing work.

I am not creating any object with new instance. If I create new object, i can understand spring will throw null pointer instance as the object is not in spring container.

Also, I am getting this issue when I mock the object in test class.

package com.imosadapter.srd.main;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.trafigura.titan.imosadapter.srd.constant.ApiRequestUtility;
import com.trafigura.titan.imosadapter.srd.constant.SrdApiConstant;
import com.trafigura.titan.imosadapter.srd.model.company.Company;
import com.trafigura.titan.imosadapter.srd.model.legalentity.LegalEntity;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.io.IOException;
import java.util.List;

import static org.slf4j.LoggerFactory.getLogger;

public class ImosSrdSample {

    @Autowired
    private ApiRequestUtility apiRequestUtility;
    @Value("${imos.srd.filepath}")
    private String imosFilepath;

    private static final Logger LOG = getLogger(ImosSrdMapper.class);

    ObjectMapper objectMapper = new ObjectMapper();
    String legalEntitiesOutput = null;

    public void getSrdDetails() throws IOException {
        LOG.info("Getting Legal Entities For Company Roles");
        String companyRoleOutput = apiRequestUtility.srdApiCall(SrdApiConstant.COMPANIES_URL, SrdApiConstant.COMPANIES_INPUT);
        //LOG.info("Company Role Output " + companyRoleOutput);
        try {
            List<LegalEntity> legalEntities = objectMapper.reader().forType(new TypeReference<List<LegalEntity>>() {
            }).readValue(companyRoleOutput);
            for (LegalEntity legalEntity : legalEntities) {
                LOG.info("Getting Legal Entities Information");
                legalEntitiesOutput = apiRequestUtility.srdApiCall(SrdApiConstant.LEGALENTITIES_URL,
                        apiRequestUtility.jsonInput(legalEntity.getIdentifier(), SrdApiConstant.GUID));
                //LOG.info("Legal Entities Output " + legalEntitiesOutput);

                Company company = objectMapper.readValue(legalEntitiesOutput, Company.class);
            }
        } catch (IOException e) {
            LOG.error("No File Path found. So File not generated", e);
        }
    }
}

I am having a constant file which has some static fields in which I have described the base URL and the type of input which the call needs.

package com.imosadapter.srd.constant;
import org.springframework.stereotype.Component;

@Component
public class SrdApiConstant {

    private SrdApiConstant() {
    }

    public static final String BASE_URL = "http://localhost:9100/referencedatanew/";
    public static final String COMPANIES_URL = "LegalEntitiesService/GetCompanies";
    public static final String LEGALENTITIES_URL = "LegalEntitiesService/GetCompanyByGUID";


    public static final String COMPANIES_INPUT = "{\"CompanyCode\":\"AGSHCODE\"}";

    public static final String GUID = "Guid";
    public static final String LE_GUID = "LegalEntityGUID";
}

Another class for creating a input and getting a connection.

package com.imosadapter.srd.constant;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class ApiRequestUtility {

    private static final Logger LOG = LoggerFactory.getLogger(ApiRequestUtility.class);

    public String srdApiCall(String url, String jsonInputString) throws IOException {
        String user = SrdApiConstant.USER;
        String companyOutput = null;
        StringBuffer result = new StringBuffer();
        String baseUrl = SrdApiConstant.BASE_URL + url;

        URL companyUrl = new URL(SrdApiConstant.BASE_URL + url);
        HttpURLConnection conn = (HttpURLConnection) companyUrl.openConnection();
        conn.setDoOutput(true);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setRequestProperty("User", "user");
        OutputStream os = conn.getOutputStream();
        os.write(jsonInputString.getBytes());
        os.flush();
        if (conn.getResponseCode() != 200) {
            throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
        }
        BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
        LOG.info("Output from Server .... \n");
        while ((companyOutput = br.readLine()) != null) {
            result.append(companyOutput);

        }
        br.close();
        conn.disconnect();
        LOG.info("url : " + baseUrl);
        return result.toString();
    }

    public String jsonInput(String guid, String guidType) throws JsonProcessingException {
        String jsonString;
        ObjectMapper mapper = new ObjectMapper();
        ObjectNode srdInputJson = mapper.createObjectNode();
        if (SrdApiConstant.GUID.equalsIgnoreCase(guidType)) {
            srdInputJson.put("Guid", guid);
        } else if (SrdApiConstant.LE_GUID.equalsIgnoreCase(guidType)) {
            srdInputJson.put("LegalEntityGUID", guid);
        }
        jsonString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(srdInputJson);
        LOG.info("JSON String " + jsonString);
        return jsonString;
    }
}

And the test class

package com.imosadapter.srd.main;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.trafigura.titan.imosadapter.srd.constant.ApiRequestUtility;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.test.util.ReflectionTestUtils;

import javax.xml.bind.JAXBContext;

import static org.junit.Assert.*;
import static org.mockito.MockitoAnnotations.initMocks;

public class ImosSrdSampleTest {


    @InjectMocks
    private ImosSrdSample imosSrdSample;

    @Mock
    private JAXBContext jaxbContext;

    @Mock
    private ObjectMapper objectMapper;

    @Mock
    private ApiRequestUtility apiRequestUtility;

    @Before
    public void setUp() throws Exception {
        initMocks(this);
        ReflectionTestUtils.setField(imosSrdSample, "imosFilepath", "src/test/resources/");
    }

    @Test
    public void getSrdDetails() throws Exception {
        imosSrdSample.getSrdDetails();
    }

}

Am getting null pointer exception as the response.

java.lang.NullPointerException
    at com.trafigura.srd.main.ImosSrdSample.getSrdDetails(ImosSrdSample.java:35)
    at com.trafigura.srd.main.ImosSrdSampleTest.getSrdDetails(ImosSrdSampleTest.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
  • From a more general standpoint, you're mixing a lot of concerns in that `ImosSrdSample`, and that's going to make tests unnecessarily difficult. Furthermore, it looks like you're duplicating a lot of functionality Spring gives you for free; I suspect that all of this can be replaced with `RestTemplate`. – chrylis -cautiouslyoptimistic- Feb 19 '18 at 08:16
  • As a tip for this sort of stuff - have you considered testing at a higher level and mocking out the whole API interaction with something like WireMock? http://wiremock.org/ Alternatively, since you're using Spring, you could use MockMvc - https://docs.spring.io/spring-security/site/docs/current/reference/html/test-mockmvc.html – f1dave Feb 19 '18 at 08:16
  • @Mohamed Safi Could you please provide the smallest example as you could. Try to narrow this example. You wrote you got proper json from service. So I assume problem is further with deserialization. It would be better to find the problem. – tmucha Feb 19 '18 at 08:18
  • @f1dave As far as I can tell, he's testing the other side of things--the REST client. – chrylis -cautiouslyoptimistic- Feb 19 '18 at 08:20
  • @tmucha are you asking for pojo sample? Actually, when I unit test, am getting null pointer exception @ List legalEntities = objectMapper.reader().forType(new TypeReference>() { }).readValue(companyRoleOutput); – Mohamed Safi Feb 19 '18 at 08:34
  • @chrylis I dont think this is a duplicate. Am not asking why autowiring gives me the null pointer exception. While I mock, i am getting null pointer execpetion. – Mohamed Safi Feb 19 '18 at 08:36
  • You're getting the NPE at `apiRequestUtility.srdApiCall()` because `apiRequestUtility` is null. – chrylis -cautiouslyoptimistic- Feb 19 '18 at 08:36
  • But it happens only when I use mock in ImosSrdSampleTest. ex: @Mock private ApiRequestUtility apiRequestUtility; and it happens in the test class. And Autowiring doesnt throw any issue in main class. I can autowire successfully. – Mohamed Safi Feb 19 '18 at 08:40
  • Am getting NPE exactly at @Test public void getSrdDetails() throws Exception { imosSrdSample.getSrdDetails(); } – Mohamed Safi Feb 19 '18 at 10:07
  • @chrylis This is not a duplicate question. Just see the code and the error stacktrace I have posted. Just see the stacktrace. This is not a autowired issue. I am getting error exactly when I test. – Mohamed Safi Feb 23 '18 at 05:45

0 Answers0