How to test custom Object via #JsonTest in Spring? - json

I have my DeskDTO class that I have to test (guess I should). I found this toutorial: https://dzone.com/articles/testing-data-transfer-object-and-rest-controllers on internet but there is no explanation how to test custom class which my main class contains. To be clear:
My DeskDTO:
public class DeskDTO {
private Long deskId;
private String deskNumber;
private String additionalNote;
private LocalizationDTO localization;
private Set<ElectronicEquipmentDTO> electronicEquipments;
My test class:
#SpringBootTest(classes = ReliceApplication.class)
#RunWith(SpringRunner.class)
public class DeskDTOTest {
private JacksonTester<DeskDTO> jacksonTester;
private static final String DESK_NUMBER = "4-124";
private static final String ADDITIONAL_NOTE = "Very good desk";
private static LocalizationDTO localization;
private static Set<ElectronicEquipmentDTO> electronicEquipments;
private DeskDTO deskDTO;
#Before
public void setup() throws ParseException { //yes I know Im noob, Im still learning
ObjectMapper objectMapper = new ObjectMapper();
JacksonTester.initFields(this, objectMapper);
BuildingDTO buildingDTO = new BuildingDTO();
buildingDTO.setNameOfBuilding("Building D");
FloorDTO floorDTO = new FloorDTO();
floorDTO.setFloorNumber(4);
floorDTO.setBuilding(buildingDTO);
localization = new LocalizationDTO();
localization.setFloor(floorDTO);
localization.setxAxis(5);
localization.setyAxis(6);
ElectronicEquipmentDTO electronicEquipment = new ElectronicEquipmentDTO();
electronicEquipment.setAdditionalNote("Nice laptop");
electronicEquipment.setType(ElectronicEquipmentType.PC);
electronicEquipment.setClient("Lufthansa");
electronicEquipment.setExternalId("WS-1234");
electronicEquipment.setLocalization(localization);
electronicEquipments = new HashSet<>();
electronicEquipments.add(electronicEquipment);
deskDTO = new DeskDTO(DESK_NUMBER, ADDITIONAL_NOTE, localization, electronicEquipments);
}
private <T> T asParsedJson(Object object) throws JsonProcessingException {
String json = new ObjectMapper().writeValueAsString(object);
return JsonPath.read(json, "$");
}
#Test //this is working
public void setDeskNumberSerializes() throws IOException {
assertThat(this.jacksonTester.write(deskDTO))
.extractingJsonPathStringValue("#.deskNumber")
.isEqualTo(DESK_NUMBER);
}
#Test //same
public void setAdditionalNoteSerializes() throws IOException {
assertThat(this.jacksonTester.write(deskDTO))
.extractingJsonPathStringValue("#.additionalNote")
.isEqualTo(ADDITIONAL_NOTE);
}
#Test //this does not work
public void setLocalizationSerializes() throws IOException {
assertThat(this.jacksonTester.write(deskDTO))
.extractingJsonPathStringValue("#.localization")
.isEqualTo(localization);
}
#Test //this set does not work either
public void setElectronicEquipmentsSerializes() throws IOException {
assertThat(this.jacksonTester.write(deskDTO))
.extractingJsonPathArrayValue("#.electronicEquipments")
.isEqualTo(electronicEquipments);
}
}
When I am using .extractingJsonPathStringValue I've got:
java.lang.AssertionError: Expected a string at JSON path "#.localization" but found: {floor={floorId=null, floorNumber=4, building={buildingId=null, nameOfBuilding=Building D}}, xAxis=5, yAxis=6}
and when I am using .extractingJsonPathMapValue I've got:
org.opentest4j.AssertionFailedError:
Expecting:
<{"floor"={"building"={"buildingId"=null, "nameOfBuilding"="Building D"}, "floorId"=null, "floorNumber"=4}, "xAxis"=5, "yAxis"=6}>
to be equal to:
<com.mrfisherman.relice.Dto.LocalizationDTO#2aafa84f>
but was not.
Expected :com.mrfisherman.relice.Dto.LocalizationDTO#2aafa84f
Actual :{floor={floorId=null, floorNumber=4, building={buildingId=null, nameOfBuilding=Building D}}, xAxis=5, yAxis=6}

Related

Junit Mockito for global java.util.Map

I am trying to Test a method but it has a global variable which is null, Please guide me so I can assign value to global variable i.e. a Map
My Junit:
public class ErrorTest {
#Mock
private DataSource db;
#Mock
private JdbcTemplate jdbcTemplate;
#InjectMocks
private RateServiceImpl rateService = new RateServiceImpl();
#Mock
private RaterDao raterDao;
#Resource
private MessageSource msg ;
#Mock
Map<String, StringAttribute> errorMap = new HashMap<String, StringAttribute>();
#Before
public void setup() throws IOException, InterruptedException {
MockitoAnnotations.initMocks(this);
MockMvcBuilders.standaloneSetup(rateService).build();
}
#Test
public void findAllErrors() throws Exception {
String error;
List<Error> erList = new ArrayList<>();
Error er27 = new ErrorImpl("27",
"No detail found",
"Please enter detail.");
erList.add(er27);
Error er22 = new ErrorImpl("1",
"Maximum number exceeded",
"Please contact Technical Support.");
erList.add(er22);
for (int index = 0; index < erList.size(); index++) {
StringAttribute st = new StringAttributeImpl();
st.setName(erList.get(index).getDescription());
st.setValue(erList.get(index).getResolution());
errorMap.put(erList.get(index).getCode(), st);
}
List<Error> errorList = raterDao.findAllErrors();
assertThat(errorList, is(notNullValue()));
StringAttribute map27 = errorMap.get("27");
Mockito.when(rateService.findRwxlClientError("27")).thenReturn(map27);
StringAttribute map22 = errorMap.get("22");
Mockito.when(rateService.findRwxlClientError("22")).thenReturn(map22);
assertTrue("ParseShipment failed", map27.getName().equals("No detail found"));
assertTrue("ParseShipment failed", map22.getName().equals("Please contact Technical Support."));
}
}
My Main Class:
#Service
public class RateServiceImpl implements RateService {
protected final Log logger = LogFactory.getLog(getClass());
#Autowired
private RaterDao raterDao;
private Map<String, StringAttribute> errorMap = new HashMap<String, StringAttribute>();
#Resource
private MessageSource msg;
#PostConstruct
public void init() throws Exception {
**errorMap** = findAllClientErrors();
}
public Map<String, StringAttribute> findAllClientErrors() throws Exception {
List<Error> errorList = raterDao.findAllClientErrors();
for (int index = 0; index < errorList.size(); index++) {
StringAttribute st = new StringAttributeImpl();
st.setName(errorList.get(index).getDescription());
st.setValue(errorList.get(index).getResolution());
errorMap.put(errorList.get(index).getCode(), st);
}
return errorMap;
}
#Override
public StringAttribute findClientError(String code) throws Exception {
StringAttribute error = new StringAttributeImpl();
if (code.equals(Constants.ERROR_CODE_SETTING_UNAVAILABLE)) {
error.setName(msg.getMessage("SETTING.MESSAGE.ERROR", null,null));
error.setValue(msg.getMessage("SETTING.MESSAGE.RESOLUTION", null,null));
return error;
}
StringAttribute map = errorMap.get(code);
if (map == null || map.getName().isEmpty()) {
error.setName(msg.getMessage("DEFAULT.MESSAGE", new Object[] { code }, null));
error.setValue("");
} else {
error.setName(errorMap.get(code).getName());
error.setValue(errorMap.get(code).getValue());
}
return error;
}
}
I tried multiple solution but doesn't work, some time map becomes empty or null.
Any solution works which pass my test case.
I want to test findClientError(String code) and the issue is with errorMap
So, you can use ReflectionUtils.setField method. I made a small example, it is not exactly like your code, but overall you will get the idea.
So here's my class under test. Doing almost exactly like your example. I have hello method just to test and check if it is working or not.
class RateService {
private static Map<String, Object> errorMap = new HashMap<>();
#PostConstruct
public void init () {
this.errorMap = findAllErrors();
}
private Map<String, Object> findAllErrors() {
Map<String, Object> errorMap = new HashMap<>();
errorMap.put("a", new Object());
errorMap.put("b", new Object());
errorMap.put("c", new Object());
return errorMap;
}
// a method for demo purposes
public String hello() {
if (errorMap.size() > 0) {
return String.join(",", errorMap.keySet());
} else {
return "Empty";
}
}
}
Here's my test class. The third argument of the setField method is the object that is going to be set in that field. So, you can create a mock, or real object there. I assigned a real object with dummy values. Then tested against that.
class MainTest {
private RateService rateService;
#BeforeEach
void setUp() {
this.rateService = new RateService();
}
private Map<String, Object> exampleErrorObjects() {
Map<String, Object> errorMap = new HashMap<>();
errorMap.put("x", new Object());
errorMap.put("y", new Object());
errorMap.put("z", new Object());
return errorMap;
}
#Test
void testHello() {
// given:
ReflectionTestUtils.setField(RateService.class, "errorMap", exampleErrorObjects());
// when:
final String result = this.rateService.hello();
// then:
assertEquals("x,y,z", result);
}
}
I am setting the static field in a test method because you may want your class to be in different states (based on the errorMap field) in each test.

Mockito for SimpleJdbcCall with Spring JdbcTemplate

I tried multiple way to execute the store procedure in my Junit test case to test against the out values but unfortunately nothing is working.
My Test case:
public class DataTest {
#Mock
private static DataSource ds;
#InjectMocks
private DataDaoImpl dataDao = new DataDaoImpl();
#Mock
private static JdbcTemplate jdbcTemplate;
#Mock
private static SimpleJdbcCall viewProc;
#Before
public void setUp() throws IOException, InterruptedException {
MockitoAnnotations.initMocks(this);
MockMvcBuilders.standaloneSetup(dataDao).build();
}
#BeforeClass
public static void init() throws Exception {
viewProc = new SimpleJdbcCall(ds).withSchemaName("schema")
.withProcedureName("viewProc").withoutProcedureColumnMetaDataAccess()
.declareParameters(new SqlParameter("param1", Types.VARCHAR))
.declareParameters(new SqlParameter("param2", Types.VARCHAR))
.returningResultSet("dataModules", Mockito.anyObject());
jdbcTemplate = new JdbcTemplate(ds);
}
#Test
public void findDataModules() throws Exception {
String param1 = "abc";
List<DataObj> md = new ArrayList<DataObj>();
int size = 3;
SqlParameterSource in = new MapSqlParameterSource().addValue("param1", "abc").addValue("param2",
"123");
Map map = viewProc.execute(in);
md = (List<DataObj>) map.get("data");
assertTrue("Expected Data ", md.size() >= size);
}
}
My Main class:
#Repository
public class DataDaoImpl implements DataDao {
protected Logger logger = LoggerFactory.getLogger(getClass());
#Resource(name = "db")
private DataSource db;
private SimpleJdbcCall viewProc;
private JdbcTemplate jdbcTemplate;
/**
* Initialization of Stored Procs and JDBC Template
*
* #throws Exception
*/
#PostConstruct
public void init() throws Exception {
viewProc = new SimpleJdbcCall(db).withSchemaName("schema")
.withProcedureName("viewProc").withoutProcedureColumnMetaDataAccess()
.declareParameters(new SqlParameter("param1", Types.VARCHAR))
.declareParameters(new SqlParameter("param2", Types.VARCHAR))
.returningResultSet("data", new ViewDataRowMapper());
jdbcTemplate = new JdbcTemplate(db);
}
#Override
public List<Data> findUniqueDataModules(String p1, String p2) throws Exception {
List<DataObj> dataModules = new ArrayList<DataObj>();
try {
SqlParameterSource in = new MapSqlParameterSource().addValue("param1", p1).addValue("param2",
p2);
Map map = viewUniqueDataModulesByLicense.execute(in);
dataModules = (List<DataObj>) map.get("data");
} catch (Exception e) {
//Hnadel Exception
}
return dataModules;
}
}
Above code gives exception says datasource is required.
I tried Mockito, powerMockito but it returning empty map. There is no exceptions with mock.
I am OK with any solution which can pass my test case.
Modified naming.
As much as I hate using reflection in testing, I believe it can help you in your case. Here, after initializing, I set the field viewProc to a mock object which you can use in the test. #PostConstruct is a Spring related annotation, so it will not be called while initializing it.
class DataDaoImplTest {
private DataDaoImpl dataDao;
#Mock
private DataSource dataSource;
#Mock
private SimpleJdbcCall jdbcCall;
#BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
this.dataDao = new DataDaoImpl(dataSource);
ReflectionTestUtils.setField(this.dataDao, "viewProc", jdbcCall);
}
#Test
void findUniqueDataModules() throws Exception {
// given:
Map<String, Object> map = new HashMap<>();
map.put("data", Arrays.asList(new DataDaoImpl.DataObj(), new DataDaoImpl.DataObj()));
// mocks:
when(jdbcCall.execute(any(SqlParameterSource.class))).thenReturn(map);
// when:
List<DataDaoImpl.DataObj> uniqueDataModules = this.dataDao.findUniqueDataModules("a", "b");
// then:
assertEquals(2, uniqueDataModules.size());
}
}
Another solution would be to test the method against a test database, like H2. But it won't be a unit test.

Getting NullPointerException while accessing the SuperClass method call using powermock

Getting NullPointerException while accessing the SuperClass method call using powermock
While running the below mentioned testclass getting NullPointerException error at above mentioned line in switch(super.getType())
public class CommandParamInput extends AbstractCommandParam {
public CommandParamInput(
final ParameterFeedType commandParameterSourceToSet,
final Object definedValueToSet) {
this.commandParameterSource = commandParameterSourceToSet;
this.definedValue = definedValueToSet;
}
public void evaluateValue(final FDPRequest fdpRequest)
throws EvaluationFailedException {
switch (super.getType()) {
case ARRAY:
evaluateComplexValue(fdpRequest);
break;
}
}
}
While running the below mentioned testclass getting NullPointerException error at above mentioned line in switch(super.getType())
#RunWith(PowerMockRunner.class)
#PrepareForTest({AbstractCommandParam.class,CommandParameterType.class,ParameterFeedType.class,LoggerUtil.class,Logger.class})
public class CommandParamInputTest {
private Logger loggerMock;
private FDPRequest instFDPRequest;
private FDPResponse instFDPResponse;
private FDPCacheable instFDPCacheable;
private AbstractCommandParam cmdParam;
private CommandParamInput spy;
#Mock
AbstractCommandParam absCommandParam;
#Mock
CommandParameterType cmdParameterType;
#Mock
ParameterFeedType parameterFeedType;
#InjectMocks
private CommandParamInput commandParamInput;
#Before
public void init() {
FDPRequestImpl fdoRequestImpl = new FDPRequestImpl();
fdoRequestImpl.setCircle(new FDPCircle(new Long(10),"10","test"));
fdoRequestImpl.setChannel(ChannelType.USSD);
instFDPRequest = fdoRequestImpl;
spy = PowerMockito.spy(new CommandParamInput(parameterFeedType.AUX_REQUEST_PARAM, instFDPCacheable));
}
#Test
public void testEvaluateValue()throws ExecutionFailedException,
EvaluationFailedException, FileNotFoundException, RuleException{
mockCommonObjects();
commonMockExternalCall();
absCommandParam = new CommandParamInput(parameterFeedType.AUX_REQUEST_PARAM, instFDPCacheable);
absCommandParam.setType(cmdParameterType.PARAM_IDENTIFIER);
PowerMockito.doReturn(cmdParameterType.PARAM_IDENTIFIER).when(spy).getType();
// when(absCommandParam.getType()).thenReturn(cmdParameterType.PARAM_IDENTIFIER);
PowerMockito.suppress(PowerMockito.methods(AbstractCommandParam.class, "getType"));
commandParamInput.evaluateValue(instFDPRequest);
}
}

Junit for Controller class

I have controller method and for it I am making Junit but getting Null pointer error when it calling a service method. I used power mock but still getting Null pointer.
method:
#RequestMapping(method = RequestMethod.GET, value = "/DSR.do")
public ModelAndView displayDataSourceReportPage(HttpServletRequest request,Model model) {
log.debug(" Inside displayDataSourceReportPage method ");
Map<String, Object> map = new HashMap<String, Object>();
try {
request.setAttribute(MENU_SELECTED, LABEL_MENU_SOURCEDATA);
request.setAttribute(SUB_MENU_SELECTED, LABEL_SUBMENU_DSR);
#SuppressWarnings("rawtypes")
List dataSource = dataSourceReportService.listDataSourceReportByCurrentRunInd("C");
map.put("dataSource", dataSource);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return new ModelAndView("DataSourceReport", "model", map);
}
test Method:
#InjectMocks
private DataSourceReportController dataSourceReportController;
#Mock
private DataSourceReportService dataSourceReportServiceImpl;
#InjectMocks
private DataSourceReportDAO dataSourceReportDAO = new DataSourceReportDAOImpl();
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testdisplayDataSourceReportPage() throws Exception {
PowerMockito.mockStatic(DataSourceReport.class);
PowerMockito.mockStatic(HttpServletRequest.class);
PowerMockito.mockStatic(Model.class);
PowerMockito.mockStatic(DataSourceReportService.class);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Model model = Mockito.mock(Model.class);
dataSourceReportServiceImpl = PowerMockito.mock(DataSourceReportService.class);
DataSourceReport dataSourceReport = PowerMockito.mock(DataSourceReport.class);
dataSourceReport.setCurrentRunInd("abc");
dataSourceReport.setActualFileName("Somthing");
dataSourceReport.setFileCountId(3);
dataSourceReport.setFileId(4);
dataSourceReport.setRecCount(3);
List<DataSourceReport> list = new ArrayList<DataSourceReport>();
list.add(dataSourceReport);
String currentRunInd = "currentRunInd";
Object obj =getClass();
PowerMockito.when(dataSourceReportDAO.listDataSourceReportByCurrentRunInd(currentRunInd)).thenReturn(list);
DataSourceReportController ctrl = new DataSourceReportController();
ctrl.displayDataSourceReportPage(request, model);
}
getting Null at "dataSourceReportService.listDataSourceReportByCurrentRunInd("C");"
You need to have this in the test class
PowerMockito.when(dataSourceReportService.listDataSourceReportByCurrentRunInd("C")).thenReturn(list);
before calling
ctrl.displayDataSourceReportPage(request, model);
Thanks # Arthur Zagretdinov
I tried the below code and it worked.
private MockMvc mockMvc;
#Mock
private HttpServletRequest req;
#Mock
private DataSourceReportService dataSourceReportServiceImpl;
#InjectMocks
private DataSourceReportController controller;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
#Before
public void initMocks(){
MockitoAnnotations.initMocks(this);
}
#Test
public void testdisplayDataSourceReportPage() throws Exception {
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Model model = Mockito.mock(Model.class);
DataSourceReport dataSourceReport =Mockito.mock(DataSourceReport.class);;
dataSourceReport.setCurrentRunInd("abc");
dataSourceReport.setActualFileName("Somthing");
dataSourceReport.setFileCountId(3);
dataSourceReport.setFileId(4);
dataSourceReport.setRecCount(3);
List<DataSourceReport> list = new ArrayList<DataSourceReport>();
list.add(dataSourceReport);
ModelAndView modelView = controller.displayDataSourceReportPage(request, model);
modelView.addObject(dataSourceReport);
}

How to write a junit test case for a method containing session map

I'm very new to Junit.
I'm writing junit for a interceptor.. It contains SessionMap in that.. while calling the interceptor from the test class I'm getting Null pointer exception at Session Map.
Below is my interceptor..
public String intercept(ActionInvocation actionInv) throws Exception {
ActionContext context = actionInv.getInvocationContext();
final HttpServletRequest request = (HttpServletRequest) context.get(ServletActionContext.HTTP_REQUEST);
String callerAppName = request.getParameter(CustomerPortalConstants.CALLER);
if(callerAppName == null){
//caller name is passed in header in case of OnePortal service request
callerAppName = request.getHeader(CustomerPortalConstants.CALLER);
}
SessionMap<String,Object> sessionMap = ((SessionMap<String,Object>)ActionContext.getContext().getSession());
#SuppressWarnings("unchecked")
Map<String,AccountBean> accountsMap = (Map<String,AccountBean>)sessionMap.get(CustomerPortalConstants.ACCOUNTSMAP);;
if(accountsMap == null) {
accountsMap = new HashMap<String, AccountBean>();
sessionMap.put(CustomerPortalConstants.ACCOUNTSMAP, accountsMap);
}
Im getting error at this location
((SessionMap)ActionContext.getContext().getSession());
This is my Test class..
public class MultiAccountInterceptorTest extends StrutsTestCase implements SessionAware {
/**
*
*/
private static final long serialVersionUID = 1L;
private Map<String,AccountBean> accountsMap=new HashMap<String, AccountBean>();
Map<String, Object> sessionMap;
private String callerAppName="LMP";
private final HttpServletRequest mockHttpReq = createMock(HttpServletRequest.class);
MultiAccountInterceptor interceptor = new MultiAccountInterceptor();
#SuppressWarnings("unchecked")
#Before
public void setUp() throws Exception {
sessionMap = new HashMap<String, Object>();
}
#SuppressWarnings("unchecked")
#Test
public void testIntercept() throws Exception
{
MultiAccountInterceptor mockInterceptor = PowerMock.createNicePartialMockForAllMethodsExcept(MultiAccountInterceptor.class, "intercept");
final ActionInvocation mockInvocation = createMock(ActionInvocation.class);
final ActionContext mockContext = createMock(ActionContext.class);
expect(mockInvocation.getInvocationContext()).andReturn(mockContext);
System.out.println(mockContext);
expect( (HttpServletRequest)mockContext.get(ServletActionContext.HTTP_REQUEST)).andReturn(mockHttpReq);
System.out.println(mockHttpReq);
expect(mockHttpReq.getParameter(CustomerPortalConstants.CALLER)).andReturn(callerAppName);
System.out.println("Caller app name is"+ callerAppName);
System.out.println(sessionMap);
sessionMap.put(CustomerPortalConstants.ACCOUNTSMAP, accountsMap);
System.out.println(sessionMap);
replayAll();
mockInterceptor.intercept(mockInvocation);
}
#Override
public void setSession(Map<String, Object> sessionMap) {
this.sessionMap=sessionMap;
}
}
Can anyone provide me a solution for this problem..
Thanks in advance..