Mockito:如何在测试时模拟自动变量

问题描述 投票:0回答:2

我使用JUnit和Mockito对我的Web应用程序进行单元测试。目前我正在尝试在完成DAO级别后为Service层编写测试用例。这是我的测试用例:

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;      
    }

}

制图员:

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”方法时遇到了问题:我嘲笑的一切都很好,直到我去mapper,我在这里得到了NullPointerException

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

我认为sessioVariable是空的,因为它没有在我的测试上下文中初始化,所以我试图模拟o做一些东西让我有一个有效的sessionVariable(此时内容并不重要)不在Service和Mapper中修改任何内容。

提前致谢!再见!

java testing junit mockito jacoco
2个回答
0
投票

我相信sessionVariable是空的原因,即使你明显嘲笑它,是因为ObservationMapper mapper被使用@Spy嘲笑。与@Mock不同,@Spy创建了一个被模拟对象的实例,但内部引用的所有内容都是null,除非您明确地在其中注入模拟。

解决方案1:

@Mock
SessionVariable sessionVariable;

@Mock
ScalarObservationMapper scalarMapper;

@Spy
@InjectMocks
private ObservationMapper mapper;

如果这不起作用,您可能想尝试使用@Mock而不是@Spy,然后在ObservationMapper类中模拟两个服务(sessionVariable和scalarMapper)。无论如何,你应该模拟两个服务,因为你在方法convertToDTO中使用它们。

解决方案2:

@Mock
SessionVariable sessionVariable;

@Mock
ScalarObservationMapper scalarMapper;

@Mock
private ObservationMapper mapper;

0
投票

使用@Mock注释变量并使用Mockito.when()模拟函数调用。

当(observationDAO.getStringX())thenReturn( “字符串X”);

© www.soinside.com 2019 - 2024. All rights reserved.