文章目录
一、什么是 Mock 测试
Mock通常是指,在测试一个对象A时,我们构造一些假的对象来模拟与A之间的交互,而这些Mock对象的行为是我们事先设定且符合预期。
这什么意思呢?
就是指在测试一个单元方法的时候,我们不想加载其他的类,默认其他类的功能是正常的,只测试这个方法。
好吧,我知道其实还是不太明白,那么请看示例
二、传统的单元测试Junit Test
首先看一下junit的单元测试是这样的,spring boot项目导入相关的依赖之后,
在测试类的上方注入两个注解,声明这是一个test类
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {WebApplication.class})
public class BaseTest {
}
单元方法是下面这样的,通过@Resource注解将matchSourceScoreService注入进来
@Resource
private MatchSourceScoreService matchSourceScoreService;
@Test
public void saveMatchSourceScore(){
MatchSourceScore matchSourceScore = matchSourceScoreService.selectById(6L);
matchSourceScore.setStandardCode(10d);
matchSourceScore.setUpdateBy("TEST_1221001");
XyResultModel<Long> resultModel = matchSourceScoreService.saveMatchSourceScore(matchSourceScore);
Assert.assertTrue(true);
}
测试会发现,我们启动这个test类的时候会将整个项目启动起来,如果项目过大,每次单测一个test方法都会花费很长的时间
那么mock测试与junit测试有什么区别呢?
三、Mock测试(对比junit测试)
首先看一下这个测试类
@RunWith(MockitoJUnitRunner.class)
public class UpdateStandardCodeListenerTest {
@InjectMocks
private UpdateStandardCodeService updateStandardCodeService;
@Mock
private XyDrugStandardDao xyDrugStandardDao;
private final StandardCodeExcelDTO standardCodeExcelDTO = new StandardCodeExcelDTO();
@Before
public void init() {
standardCodeExcelDTO.setStandardCode("00000000000000");
standardCodeExcelDTO.setApprovalNum("国食健字G20220206");
standardCodeExcelDTO.setStrength("默认");
standardCodeExcelDTO.setGenericName("百合康牌越橘叶黄素软胶囊");
standardCodeExcelDTO.setXyEntManufacturerName("山东威海百合生物技术股份有限公司");
}
@Test
public void testHandleStandardCodeByInputDTO1() throws CheckArgsException {
when(xyDrugStandardDao.selectList(any())).thenReturn(null);
updateStandardCodeService.handleStandardCodeByType(standardCodeExcelDTO, 4, "sys");
verify(xyDrugStandardDao, times(1)).insert(any());
}
看上去似乎和junit测试没啥区别,都需要在类上注入@RunWith注解,单元方法也是用@Test注解,
但是有变化的是:
- 有一些方法用@InjectMocks注解,有些方法用@Mock注解。
- 单元方法中有when。。。、verify。。。
- 并不需要启动整个项目,只会单独运行这个方法
四、Mock详解
1.@InjectMocks和@Mock用法
这两个注解也是为了引用类中方法,将其托管给mock管理,
比如:
- 我的目的是为了测试updateStandardCodeService类中的handleStandardCodeByType方法,那么就需要将其注解为@InjectMocks。
- 那么被@Mock注解注入的方法是handleStandardCodeByType方法中用到了xyDrugStandardDao这个类中的selectList方法去查数据库,被这个注解注入后,并不会真的去发出sql语句去查询数据库,而是根据某种规则,返回特定的值。
handleStandardCodeByType方法:
可以看到方法中有selectList和insert两个数据库的交互操作
public void handleStandardCodeByType(StandardCodeExcelDTO standardCodeExcelDTO, int type, String operator) {
Wrapper<XyDrugStandard> wrapper = new EntityWrapper<>();
List<XyDrugStandard> xyDrugStandards = xyDrugStandardDao.selectList(wrapper);
if (CollectionUtils.isEmpty(xyDrugStandards)) {
xyDrugStandardDao.insert(xyDrugStandard);
}
}
2.when用法
when(xyDrugStandardDao.selectList(any())).thenReturn(null);
这就是一条规则,对于xyDrugStandardDao类的selectList方法,any()就是参数不管是什么,都会返回null。
3.verify用法
verify(xyDrugStandardDao, times(1)).insert(any());
这是一条验证规则,验证xyDrugStandardDao的insert方法,不管参数是什么,有没有被执行1次,没有的话就报错,相当于断言Assert。
五、Mock其他常用用法
1.如何初始化数据
像我上面的那种方法,用@Before注解,初始化你的变量值,会在test方法执行前运行。
2.初始化service类中的Apollo配置
@Test
public void testHandleStandardCodeByInputDTO1() throws CheckArgsException {
setField("manufactureNameValidLength", 4);
}
public void setField(String fieldName, Object value){
Field field = XyDrugMasterCodeServiceImpl.class.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(xyDrugMasterCodeService, value);
}
比如我想给XyDrugMasterCodeServiceImpl类中的Apollo配置manufactureNameValidLength赋初值4。
就可以使用反射的方式,给配置赋初值
3.Assert.assertEquals用法
Assert.assertEquals("c", testList.get(0));
声明断言,testList的get(0)和字符串c相等。
还有一些其他用法可以参考官网https://site.mockito.org/
标签:xyDrugStandardDao,大白话,单元测试,mock,测试,注解,方法,public,Mock From: https://blog.csdn.net/weixin_45404884/article/details/140661780