没用mockito之前一直在想,springBoot junit测试时,能不能不启动整个spring项目,只加载和验证我需要的类或者方法,在项目复杂和springBoot项目中用例过多的情况下,启动整个springboot项目跑junit耗时多,而且现有的微服务架构,微服务和微服务之前通过接口交互,会导致部分用例报错,在使用了Mockito之后,发现这些问题都迎刃而解了
Mockito框架官方地址mockito,文档地址。
Mockito库能够Mock对象、验证结果以及打桩(stubbing)
在springboot的pom文件中引入org.mockito包
org.mockito
mockito-core
3.3.3
在springboot项目test报下新建一个package,然后再建一个测试类,给测试类增加注解,扫描使用@ContextConfiguration注解,只扫描使用到的类,@MockBean 将这些类通过mock的方式注入,@SpyBean当定义了spy方法则使用spy方法返回的结果,无定义则跑真实的方法
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {FugooPayServiceImpl.class,
DefaultChannelSelectorContext.class, DefaultChannelSelector.class,
PayFlowService.class, PaymentFeeService.class, FugooPayReferenceHolder.class,
PaySequenceService.class, PaymentFeeService.class})
@SpyBean(classes = {SpringUtil.class})
@MockBean(classes = {MchPayChannelConfigMapper.class, PayFlowMapper.class, RedisService.class,
EncrypteMappingInfoRedisTemplate.class, PaySequenceMapper.class, MchPayOrgService.class,
DubboProperties.class, ApplicationContext.class, RedisTemplate.class})
public class PayFlowServiceTest2 {
}
实现一个入参验证用例
package com.ses.pay.channel.gateway.route;
import cn.hutool.extra.spring.SpringUtil;
import com.ses.common.api.dto.MchPayOrgConfigDto;
import com.ses.common.api.entity.PayOrderModel;
import com.ses.common.api.enums.*;
import com.ses.exception.BusiException;
import com.ses.pay.channel.gateway.provider.FugooPayService;
import com.ses.pay.gateway.entity.FugooPayResponse;
import com.ses.pay.gateway.entity.PaymentRequest;
import com.ses.pay.gateway.framework.DubboProperties;
import com.ses.pay.gateway.framework.FugooPayReferenceHolder;
import com.ses.pay.gateway.payment.mapper.MchPayChannelConfigMapper;
import com.ses.pay.gateway.payment.mapper.PayFlowMapper;
import com.ses.pay.gateway.payment.mapper.PaySequenceMapper;
import com.ses.pay.gateway.payment.provider.impl.FugooPayServiceImpl;
import com.ses.pay.gateway.payment.router.DefaultChannelSelector;
import com.ses.pay.gateway.payment.router.DefaultChannelSelectorContext;
import com.ses.pay.gateway.payment.service.*;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static org.mockito.Mockito.*;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {FugooPayServiceImpl.class,
DefaultChannelSelectorContext.class, DefaultChannelSelector.class,
PayFlowService.class, PaymentFeeService.class, FugooPayReferenceHolder.class,
PaySequenceService.class, PaymentFeeService.class})
@SpyBean(classes = {SpringUtil.class})
@MockBean(classes = {MchPayChannelConfigMapper.class, PayFlowMapper.class, RedisService.class,
EncrypteMappingInfoRedisTemplate.class, PaySequenceMapper.class, MchPayOrgService.class,
DubboProperties.class, ApplicationContext.class, RedisTemplate.class})
public class PayFlowServiceTest2 {
private static String CARD_NO = "2021031015482106800000002";
@Autowired
private FugooPayService fugooPayService;
@MockBean(name="redisTemplate")
private RedisTemplate redisTemplate;
@MockBean
private MchPayChannelConfigMapper mchPayChannelConfigMapper;
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testfukaPayRequestDataError() {
PaymentRequest paymentRequest = new PaymentRequest();
when(mchPayChannelConfigMapper.
selectAvailableProducts(anyString(),anyString(),anyString()))
.thenReturn(buildMchPayConfigList());
PayOrderModel payOrderModel = new PayOrderModel();
payOrderModel.setCardNo(CARD_NO);
paymentRequest.setPayOrder(payOrderModel);
thrown.expect(BusiException.class);
thrown.expectMessage("proCategory & payWaysCategory & merId can not be null!!!");
fugooPayService.fukaPay(paymentRequest);
}
}