单元测试错误Mock了Mapper对象导致invocationtargetexception

今天在别人写了一半的单元测试基础上准备完成剩余的,于是写了如下测试代码:

@Mock
private FcoCertMapper fcoCertMapper;
        PowerMockito.when(fcoCertMapper.selectCertInfoList(Mockito.any(CertQueryDto.class))).thenReturn(infoVos);
        certManageServiceImpl.selectCertInfoList(dto);

执行后报错:
在这里插入图片描述
打断点发现fcoCertMapper报了空指针
在这里插入图片描述
fcoCertMapper已经使用@Mock了,没问题,问题原来是certManageServiceImpl没有使用@InjectMocks,这样fcoCertMapper就为null了。
仔细看了下,原来这个单元测试类有特殊性,该类在方法前面有静态类调用了静态方法。如果使用@InjectMocks,那么运行测试后,实例化certManageServiceImpl,首先就执行到静态类调用静态方法,然而这里还没有Mock,所以肯定会报错。

@Component
public class CertManageServiceImpl implements CertManageService {

    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(CertManageServiceImpl.class);

    @Autowired
    RsfServiceCommonClient rsfServiceCommonClient;

    ServiceAgent certManageServiceRSF = ServiceLocator.getServiceAgent(RsfAgentEnum.CERT_MANAGE_AGENT.getContract(),
            RsfAgentEnum.CERT_MANAGE_AGENT.getImplCode(),false);
}     

综上所述,这里不使用@InjectMocks,而是先mock静态类和静态方法。然后再使用Whitebox.setInternalState帮助设置fcoCertMapper实例,这样整个单元测试就运行通过了。

  @Before
    public void setUp() throws Exception {
        ConsumerContext consumerContext = mock(ConsumerContext.class);
        mockStatic(ConsumerContextFactory.class);
        when(ConsumerContextFactory.getConsumerContext(any(String.class))).thenReturn(consumerContext);
        mockStatic(ServiceLocator.class);
        when(ServiceLocator.getServiceAgent(any(String.class), any(String.class))).thenReturn(serviceAgent);
        certManageServiceImpl = new CertManageServiceImpl();
        Whitebox.setInternalState(certManageServiceImpl, "rsfServiceCommonClient", rsfServiceCommonClient);
        Whitebox.setInternalState(certManageServiceImpl, "fcoCertRecordMapper", fcoCertRecordMapper);
        Whitebox.setInternalState(certManageServiceImpl, "fcoCertMapper", fcoCertMapper);
    }

附完整单元测试代码:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ConsumerContextFactory.class, ServiceLocator.class})
@SuppressStaticInitializationFor({"com.suning.rsf.consumer.ServiceAgent","com.suning.rsf.consumer.ServiceLocator"})
public class CertManageServiceImplTest {

    CertManageServiceImpl certManageServiceImpl;

    @Mock
    RsfServiceCommonClient rsfServiceCommonClient;

    @Mock
    ServiceAgent serviceAgent;

    @Mock
    FcoCertRecordMapper fcoCertRecordMapper;

    @Mock
    private FcoCertMapper fcoCertMapper;


    @Before
    public void setUp() throws Exception {
        ConsumerContext consumerContext = mock(ConsumerContext.class);
        mockStatic(ConsumerContextFactory.class);
        when(ConsumerContextFactory.getConsumerContext(any(String.class))).thenReturn(consumerContext);
        mockStatic(ServiceLocator.class);
        when(ServiceLocator.getServiceAgent(any(String.class), any(String.class))).thenReturn(serviceAgent);
        certManageServiceImpl = new CertManageServiceImpl();
        Whitebox.setInternalState(certManageServiceImpl, "rsfServiceCommonClient", rsfServiceCommonClient);
        Whitebox.setInternalState(certManageServiceImpl, "fcoCertRecordMapper", fcoCertRecordMapper);
        Whitebox.setInternalState(certManageServiceImpl, "fcoCertMapper", fcoCertMapper);
    }

    @After
    public void tearDown() throws Exception {

    }

    @Test(expected = AppException.class)
    public void certApply() throws Exception {
        CertRecordDto dto = new CertRecordDto();
        PowerMockito.when(rsfServiceCommonClient.rsfInvoke(Mockito.any(ServiceAgent.class),Mockito.anyString(),Mockito.anyMap())).thenThrow(new TimeoutException());
        certManageServiceImpl.certApply(dto);
    }

@Test
    public void selectCertInfoListTest(){
        CertQueryDto dto = new CertQueryDto();
        dto.setSerialNoStr("1");
        dto.setCertStatus("01");
        dto.setEndTime("2019-02-02");
        List<CertInfoVo> infoVos = new ArrayList<>();
        CertInfoVo certInfoVo = new CertInfoVo();
        certInfoVo.setId(1L);
        certInfoVo.setCertStatus("01");
        infoVos.add(certInfoVo);
        PowerMockito.when(fcoCertMapper.selectCertInfoList(Mockito.any(CertQueryDto.class))).thenReturn(infoVos);
        certManageServiceImpl.selectCertInfoList(dto);
    }
}

逻辑代码:

@Component
public class CertManageServiceImpl implements CertManageService {

    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(CertManageServiceImpl.class);

    @Autowired
    RsfServiceCommonClient rsfServiceCommonClient;

    ServiceAgent certManageServiceRSF = ServiceLocator.getServiceAgent(RsfAgentEnum.CERT_MANAGE_AGENT.getContract(),
            RsfAgentEnum.CERT_MANAGE_AGENT.getImplCode(),false);

    @Autowired
    FcoCertRecordMapper fcoCertRecordMapper;

    @Autowired
    private FcoCertMapper fcoCertMapper;

    @Override
    public List<CertInfoVo> selectCertInfoList(CertQueryDto dto) {
        if (StringUtils.isNotEmpty(dto.getSerialNoStr())) {
            dto.setSerialNo(Integer.parseInt(dto.getSerialNoStr()));
        }
        String endtime = dto.getEndTime();
        if (StringUtils.isNotEmpty(endtime)) {
            DateTimeFormatter df = DateTimeFormat.forPattern(DateConstant.DATEFORMATE_YYYY_MM_DD);
            Date dateTime = df.parseDateTime(endtime).toDate();
            String et = DateUtils.formatDate(DateUtils.addDate(dateTime, 1), DateConstant.DATEFORMATE_YYYY_MM_DD);
            dto.setEndTime(et);
        }
        List<CertInfoVo> certDtos = fcoCertMapper.selectCertInfoList(dto);
        for (CertInfoVo certDto:certDtos
             ) {
            certDto.setCertStatus(CertStatusEnum.getDescriptionFromCode(certDto.getCertStatus()));
        }
        return certDtos;
    }

    @Override
    public CertResult certApply(CertRecordDto certRecordDto) {
        SdcReqDto sdcReqDto = buildSdcReqDto(certRecordDto);
        LOGGER.info("cert apply.start, request:{}", sdcReqDto);
        Map<String, Object> result;
        try {
            result = (Map<String, Object>) rsfServiceCommonClient.rsfInvoke(certManageServiceRSF,
                    RsfMethodEnum.CERT_MANAGE_AGENT_certApply.getMethod(), BeanToMapUtils.bean2Map(sdcReqDto));
        } catch (TimeoutException ex) {
            LOGGER.error("certApply调用{}时超时异常,ex:{}", ex);
            throw new AppException(CoreErrorCode.RSF_TIME_OUT_FAILURE, CoreErrorCode.RSF_TIME_OUT_FAILURE_CN);
        } catch (RSFException ex) {
            LOGGER.error("certApply调用{}时RSF异常,ex:{}", ex);
            throw new AppException(CoreErrorCode.RSF_EXCEPTION_FAILURE, CoreErrorCode.RSF_EXCEPTION_FAILURE_CN);
        } catch (Exception exc) {
            LOGGER.error("certApply调用{}时异常,ex:{}", exc);
            throw new AppException(CoreErrorCode.OTHER_EXCEPTION_FAILURE, CoreErrorCode.OTHER_EXCEPTION_FAILURE_CN);
        }
        checkSuccess(result, ReturnCode.HANDLE_SUCCESS);
        LOGGER.info("cert apply.end, response:{}", result);

        SdcResDto sdcResDto = JSON.parseObject(JSON.toJSONString(result), SdcResDto.class);
        CertResult certResult = new CertResult();
        certResult.setUserNo(sdcReqDto.getUserNo());
        BeanUtils.copyProperties(sdcResDto, certResult);

        CertRecordDto recordDto = new CertRecordDto();
        recordDto.setUserNo(sdcReqDto.getUserNo());
        recordDto.setTelNo(sdcReqDto.getTelNo());
        recordDto.setSn(certResult.getSn());
        recordDto.setDn(certResult.getDn());

        /**
         * 删除并重新保存新记录
         */
        deleteCertRecord(sdcReqDto.getUserNo());
        saveCertRecord(recordDto);

        return certResult;
    }
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值