vendredi 28 septembre 2018

Mockito : how to mock an autowired variable while testing

I'm unit testing my web application using JUnit and Mockito. At the moment i'm trying to write testcases for Service layer after completing the DAO level. This is my test case:

package it.ingeniars.testService;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

import static org.mockito.Mockito.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.assertj.core.api.Assertions.*;

import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;

import it.ingeniars.constants.EasycareEnumTypes.ActivityType;
import it.ingeniars.dao.interf.AccountDAOInterface;
import it.ingeniars.dao.interf.CareTeamDAOInterface;
import it.ingeniars.dao.interf.DeviceDAOInterface;
import it.ingeniars.dao.interf.ObservationDAOInterface;
import it.ingeniars.dto.DeviceDTO;
import it.ingeniars.dto.ObservationDTO;
import it.ingeniars.exception.ECForbiddenException;
import it.ingeniars.mapper.DeviceMapper;
import it.ingeniars.mapper.ObservationMapper;
import it.ingeniars.model.Account;
import it.ingeniars.model.Device;
import it.ingeniars.model.Observation;
import it.ingeniars.service.DeviceService;
import it.ingeniars.service.ObservationService;
import it.ingeniars.testConf.MockDAOUtils;
import it.ingeniars.testConf.MockDTOUtils;
import it.ingeniars.testConf.TestContext;
import it.ingeniars.utilities.DatetimeUtils;
import it.ingeniars.utilities.SessionVariable;

@ContextConfiguration(classes = {TestContext.class})
@ComponentScan({"it.ingeniars.service"})
public class ObservationServiceTest extends AbstractTransactionalJUnit4SpringContextTests {

    @Autowired
    private MockDAOUtils mockDAOUtils;

    @Mock
    SessionVariable sessionVariable;

    @Mock
    private ObservationDAOInterface observationDAOMock;

    @Mock
    private AccountDAOInterface accountDAOMock;

    @Mock
    private CareTeamDAOInterface careTeamDAOMock;

    @Spy
    private ObservationMapper mapper;

    @InjectMocks
    private ObservationService service;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    /**
     * {getObservationList}
     * 
     * [account]
     * -------------------------------------------------------------------------------------------------------
     * | id   | enabled | locked | account_expired | password_expired | data_handling | role                 |
     * -------------------------------------------------------------------------------------------------------
     * | 1000 | 1       | 0      | 0               | 0                | 1             | patient              |  targetAccount : valid patient account
     * | 1001 | 1       | 0      | 0               | 0                | 1             | general_practitioner |  callerAccount : medic in patient careteam
     * | 1002 | 1       | 0      | 0               | 0                | 0             | patient              |  targetAccount : invalid patient account
     * | 1003 | 1       | 0      | 0               | 0                | 1             | patient              |  callerAccount : patient with ID different from patientID
     * -------------------------------------------------------------------------------------------------------
     * 
     * [Observation]
     * ------------------------------------------------------------------------
     * | id | activity_type | medical_record_id | execution_date      | Note  |
     * ------------------------------------------------------------------------
     * | 1  | act_pressure  | 1                 | 2018-06-01 11:00:00 | Note1 |
     * | 2  | act_oximetry  | 1                 | 2018-06-01 14:00:00 | Note2 |
     * ------------------------------------------------------------------------
     * 
     */
    @Test
    public void test_case_u0048() throws Exception {

        // Taking method name
        String methodName = new Object() {
        }.getClass().getEnclosingMethod().getName();
        // Building test case file path
        String path = mockDAOUtils.getTc_path() + methodName + mockDAOUtils.getXml_ext();

        // Setting the test environment
        List<Account> accountList = mockDAOUtils.mockAccount(path);
        List<Observation> observationList = mockDAOUtils.mockObservation(path);
        List<ActivityType> activityTypeList = new ArrayList<ActivityType>();
        activityTypeList.add(ActivityType.act_pressure);
        activityTypeList.add(ActivityType.act_oximetry);
        Date startDate = mockDAOUtils.getFormat().parse("2018-06-01 00:00:00");
        Date endDate = mockDAOUtils.getFormat().parse("2018-06-01 23:59:59");


        // [RESULT CASE - VALID TARGET ACCOUNT / MEDIC CALLER ACCOUNT IN PATIENT CARE TEAM]
        Mockito.when(accountDAOMock.findByPersonId(1000L)).thenReturn(accountList.get(0));
        Mockito.when(careTeamDAOMock.isCareTeam(1000L, 1001L)).thenReturn(true);
        Mockito.when(sessionVariable.getTimezone()).thenReturn("GMT-8:00");
        System.out.println("[SV] = " + sessionVariable.getTimezone());
        Mockito.when(observationDAOMock.getListByMedRecIdAndActivityTypeAndDateRange(1L, activityTypeList, startDate, endDate)).thenReturn(observationList);
        List<ObservationDTO> observationDTOList = service.getObservationList(1000L, accountList.get(1), activityTypeList, startDate, endDate);

    }

}

Service Layer :

package it.ingeniars.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import it.ingeniars.constants.EasycareEnumTypes.ActivityType;
import it.ingeniars.constants.EasycareEnumTypes.ApplicationRole;
import it.ingeniars.dao.interf.AccountDAOInterface;
import it.ingeniars.dao.interf.CareTeamDAOInterface;
import it.ingeniars.dao.interf.ObservationDAOInterface;
import it.ingeniars.dto.ObservationDTO;
import it.ingeniars.exception.ECForbiddenException;
import it.ingeniars.exception.ECNotFoundException;
import it.ingeniars.mapper.ObservationMapper;
import it.ingeniars.model.Account;
import it.ingeniars.model.Observation;
import it.ingeniars.utilities.DatetimeUtils;
import it.ingeniars.utilities.SessionVariable;

@ComponentScan({"it.ingeniars.mapper","it.ingeniars.dao.impl"})
@Service
@Transactional
public class ObservationService {

    @Autowired
    ObservationDAOInterface observationDAO;

    @Autowired
    SessionVariable sessionVariable;

    @Autowired
    ObservationMapper observationMapper;

    @Autowired
    AccountDAOInterface accountDAO;

    @Autowired
    CareTeamDAOInterface careTeamDAO;

    /**
     * Provide the list of ObservationDTO of the patient included in the period and matching the list of types
     * 
     * @param patientId id of the patient
     * @param activityTypes list of activity types
     * @param startDate beginning of the period
     * @param endDate end of the period
     * @return the list of observations, eventually empty
     * 
     */

    @Transactional(readOnly=true)
    public List<ObservationDTO> getObservationList(long patientId, Account callerAccount, List<ActivityType> activityTypes, Date startDate, Date endDate){  

        // target permission check      
        Account targetAccount = accountDAO.findByPersonId(patientId);
        if(targetAccount == null) {
            throw new ECNotFoundException();
        } else if (!targetAccount.isValid()){
            throw new ECForbiddenException();
        } else if (targetAccount.getFirstApplicationRole() != ApplicationRole.patient) {
            throw new ECForbiddenException();
        }

        // caller permission check
        switch (callerAccount.getFirstApplicationRole()) {
            case general_practitioner:
            case medical_specialist:
                if(!careTeamDAO.isCareTeam(targetAccount.getId(), callerAccount.getId())) {
                    throw new ECForbiddenException();
                }
                break;
            case patient:
                if(targetAccount.getId() != callerAccount.getId()){
                    throw new ECForbiddenException();
                }
                break;
            default:
                throw new ECForbiddenException();       
        }

        List<Observation> observationList = observationDAO.getListByMedRecIdAndActivityTypeAndDateRange(targetAccount.getMedicalRecord().getId(), activityTypes, startDate, endDate);
        List<ObservationDTO> observationDTOList = new ArrayList<>();

        for(Observation item : observationList){
            observationDTOList.add(observationMapper.convertToDTO(item));
        }

        return observationDTOList;      
    }

}

Mapper:

package it.ingeniars.mapper;

import java.util.Map;
import java.util.TimeZone;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import it.ingeniars.constants.EasycareEnumTypes.ObservationExamType;
import it.ingeniars.constants.EasycareEnumTypes.ObservationParameterType;
import it.ingeniars.dto.ObservationDTO;
import it.ingeniars.dto.ScalarObservationDTO;
import it.ingeniars.dto.SignalObservationDTO;
import it.ingeniars.model.Observation;
import it.ingeniars.model.ObservationScalar;
import it.ingeniars.model.ObservationSignal;
import it.ingeniars.utilities.DatetimeUtils;
import it.ingeniars.utilities.SessionVariable;

@Component
public class ObservationMapper extends Mapper<ObservationDTO,Observation> {

    @Autowired
    SessionVariable sessionVariable;

    @Autowired
    ScalarObservationMapper scalarMapper;

    @Override
    public ObservationDTO convertToDTO(Observation entity) {
        ObservationDTO observationDTO = new ObservationDTO();
        observationDTO.setActivityType(entity.getActivityType());
        observationDTO.setActivityLabel(entity.getActivityType().getLabelCode());
        //observationDTO.setScheduleActivityId(entity.getScheduleActivity() != null ? entity.getScheduleActivity().getId() : null);
        observationDTO.setMedicalRecordId(entity.getMedicalRecord().getId());
        System.out.println("[SV] = " + sessionVariable.getTimezone());
        observationDTO.setExecutionDate(DatetimeUtils.dateToDatetimeISO8601(entity.getExecutionDate(),TimeZone.getTimeZone(sessionVariable.getTimezone())));
        observationDTO.setId(entity.getId());
        observationDTO.setNote(entity.getNote());

        for(ObservationScalar entityScalarObs : entity.getScalarObservationList()){
            ScalarObservationDTO scalarObsDTO = scalarMapper.convertToDTO(entityScalarObs);         
            observationDTO.getScalarObservationList().put(scalarObsDTO.getParameterType(), scalarObsDTO);
        }

        SignalObservationMapper signalMapper = new SignalObservationMapper();
        for(ObservationSignal entitySignalObs : entity.getSignalObservationList()){
            SignalObservationDTO signalObsDTO = signalMapper.convertToDTO(entitySignalObs);         
            observationDTO.getSignalObservationList().put(signalObsDTO.getType(), signalObsDTO);
        }

//      Hibernate.initialize(observationDTO.getScalarObservationList());
//      Hibernate.initialize(observationDTO.getSignalObservationList());
        return observationDTO;
    }

    @Override
    public Observation convertToEntity(ObservationDTO dto) {
        Observation observation = new Observation();
        observation.setActivityType(dto.getActivityType());
        observation.setExecutionDate(DatetimeUtils.stringToDate(dto.getExecutionDate()));
        observation.setNote(dto.getNote());

        for(Map.Entry<ObservationParameterType,ScalarObservationDTO> scalarObsDTO : dto.getScalarObservationList().entrySet()){
            if (scalarObsDTO.getValue() != null){//empty field
                observation.getScalarObservationList().add(scalarMapper.convertToEntity(scalarObsDTO.getValue()));
            }
        }

        SignalObservationMapper signalMapper = new SignalObservationMapper();
        for(Map.Entry<ObservationExamType,SignalObservationDTO> signalObsDTO : dto.getSignalObservationList().entrySet()){
            if (signalObsDTO.getValue() != null){
                observation.getSignalObservationList().add(signalMapper.convertToEntity(signalObsDTO.getValue()));
            }
        }       

        return observation;
    }

    @Override
    public void updateEntity(ObservationDTO dto, Observation entity) {
        // TODO Auto-generated method stub

    }

}

My problem comes while trying to test the "getObservationList" method of the Service : everything I mocked works good until I go to the mapper, where i got NullPointerException here

observationDTO.setExecutionDate(DatetimeUtils.dateToDatetimeISO8601(entity.getExecutionDate(),TimeZone.getTimeZone(sessionVariable.getTimezone())));

I think that the sessioVariable is null due to the fact that it isn't initialized in my test context, so I'm trying to mock o do some stuff to let me have a valid sessionVariable (the content is not important at this moment) not modifying nothing in Service and Mapper.

Thanks in advance! Bye!

Aucun commentaire:

Enregistrer un commentaire