Mockito: как смоделировать переменную с автопроводкой во время тестирования - PullRequest
0 голосов
/ 28 сентября 2018

Я тестирую свое веб-приложение с использованием JUnit и Mockito.В настоящее время я пытаюсь написать тестовые сценарии для уровня обслуживания после завершения уровня DAO.Это мой тестовый пример:

package it.********.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.********.constants.EasycareEnumTypes.ActivityType;
import it.********.dao.interf.AccountDAOInterface;
import it.********.dao.interf.CareTeamDAOInterface;
import it.********.dao.interf.DeviceDAOInterface;
import it.********.dao.interf.ObservationDAOInterface;
import it.********.dto.DeviceDTO;
import it.********.dto.ObservationDTO;
import it.********.exception.ECForbiddenException;
import it.********.mapper.DeviceMapper;
import it.********.mapper.ObservationMapper;
import it.********.model.Account;
import it.********.model.Device;
import it.********.model.Observation;
import it.********.service.DeviceService;
import it.********.service.ObservationService;
import it.********.testConf.MockDAOUtils;
import it.********.testConf.MockDTOUtils;
import it.********.testConf.TestContext;
import it.********.utilities.DatetimeUtils;
import it.********.utilities.SessionVariable;

@ContextConfiguration(classes = {TestContext.class})
@ComponentScan({"it.********.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);

    }

}

Уровень обслуживания:

package it.********.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.********.constants.EasycareEnumTypes.ActivityType;
import it.********.constants.EasycareEnumTypes.ApplicationRole;
import it.********.dao.interf.AccountDAOInterface;
import it.********.dao.interf.CareTeamDAOInterface;
import it.********.dao.interf.ObservationDAOInterface;
import it.********.dto.ObservationDTO;
import it.********.exception.ECForbiddenException;
import it.********.exception.ECNotFoundException;
import it.********.mapper.ObservationMapper;
import it.********.model.Account;
import it.********.model.Observation;
import it.********.utilities.DatetimeUtils;
import it.********.utilities.SessionVariable;

@ComponentScan({"it.********.mapper","it.********.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.********.mapper;

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

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

import it.********.constants.EasycareEnumTypes.ObservationExamType;
import it.********.constants.EasycareEnumTypes.ObservationParameterType;
import it.********.dto.ObservationDTO;
import it.********.dto.ScalarObservationDTO;
import it.********.dto.SignalObservationDTO;
import it.********.model.Observation;
import it.********.model.ObservationScalar;
import it.********.model.ObservationSignal;
import it.********.utilities.DatetimeUtils;
import it.********.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

    }

}

Моя проблема возникает при попытке протестировать метод "getObservationList"Службы: все, что я высмеивал, работает хорошо, пока я не перейду к мапперу, где я получил NullPointerException здесь

наблюдениеDTO.setExecutionDate (DatetimeUtils.dateToDatetimeISO8601 (entity.getExecutionDate (), TimeZone.getTimeZone (sessionVariable.getTimezone))));

Я думаю, что sessioVariable имеет значение null из-за того, что он не инициализирован в моем тестовом контексте, поэтому я пытаюсь сделать какие-то вещи, чтобы у меня был допустимый sessionVariable(содержание не важно в данный момент) не изменяет ничего в Service и Mapper.

Заранее спасибо!Bye!

Ответы [ 2 ]

0 голосов
/ 28 сентября 2018

Я полагаю, что причина sessionVariable является нулевой, даже если вы явно дразните ее, потому что ObservationMapper mapper подделан с помощью @Spy.В отличие от @Mock, @Spy создает экземпляр объекта, который будет смоделирован, но все, на что ссылается внутри, является нулевым, если вы явно не добавляете в него макеты.

Решение 1:

@Mock
SessionVariable sessionVariable;

@Mock
ScalarObservationMapper scalarMapper;

@Spy
@InjectMocks
private ObservationMapper mapper;

Еслиэто не сработает, вы можете попробовать использовать @Mock вместо @Spy, а затем использовать оба сервиса (sessionVariable и scalarMapper) внутри класса ObservationMapper.В любом случае, вы должны смоделировать обе службы, так как вы используете обе из них в методе convertToDTO.

Решение 2:

@Mock
SessionVariable sessionVariable;

@Mock
ScalarObservationMapper scalarMapper;

@Mock
private ObservationMapper mapper;
0 голосов
/ 28 сентября 2018

Создайте аннотацию для переменной с помощью @Mock и смоделируйте вызовы функций с помощью Mockito.when ().

when (наблюдениеDAO.getStringX ()). ThenReturn ("stringx");

...