我是靠谱客的博主 等待大地,最近开发中收集的这篇文章主要介绍单元测试和MockandPowerMock,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Mockito基础
官网:
https://javadoc.io/static/org.mockito/mockito-core/4.1.0/org/mockito/Mockito.html#0.2

  1. 默认情况下,对于有返回值的方法,mock根据情况返回一个null/基础类型(包装类型)/空集合;对于void则doNothing

  2. thenReturn在spy的时候会先走一遍方法体,然后将结果mock掉,,用doReturn则不走方法体,可以避免真实方法的调用,如果不用spy一般推荐thenReturn

  3. 一般而已do开头的方法两种使用场景**:
    (1)处理void方法,因为void无法放在括号内
    (2)在spy时为避免调用真实方法,则使用do*
    4.如果简单的thenThrow或者thenReturn不能满足,则自定义answer接口
    5.spy()用在真实对象上,可以只mock部分方法, 该部分必须使用do 而不是when开头*
    6 spy调用没有stub的方法时 什么都不会发生

  4. 注解@spy替代spy(Object)
    @Spy BeerDrinker drinker = new BeerDrinker();
    @mock 替代mock(Class clz)


```bash
//5. 类上必须配合@RunWith(MockitoJUnitRunner.class)
@Mock
ParamCacheServiceImpl service;

@InjectMocks 在构建mock对象时,对于已经 存在的mock对象直接将其注入到当前对象的属性中,需要有有参构造或者 +setter
```bash
@Autowired
private ResetDataService resetDataService;
public ResetDataController( ResetDataService resetDataService) {
this.resetDataService = resetDataService;
}
.....
@Mock
ParamCacheServiceImpl service;
@InjectMocks
ResetDataController controller;

ps:
在springboottest环境中一般不用类上加注解,但是需要用spy
8.可以测试抽象类的抽象方法 版本2.7+
eg:

 // 可以测试抽象类的抽象方法 版本2.7+
AbstractBase base = spy(AbstractBase.class);
// test2是抽象方法
doReturn("test abstract").when(base).test2();
base.test1();
  1. ArgumentMatchers是any()/anyInt()等参数的顶级接口,可以通过lamda表达式来自定义实现
//ArgumentMatchers是any()/anyInt()等参数的顶级接口,可以通过lamda表达式来自定义实现
AbstractBase mock = mock(AbstractBase.class);
//当接口参数大于2时才mock,否则doNothing
when(mock.test3(argThat(argument -> argument.size()>2))).thenReturn(Lists.newArrayList(4,5,6));
System.out.println(mock.test3(Lists.newArrayList(1,2)));
  1. 两种只mock一部分方法的方式,spy和realMethodCall,前者适用大多真实方法,少量mock方法,后者相反

ResetDataController
mock = Mockito.spy(new ResetDataController());;
// thenReturn在spy的时候会先走一遍方法体,然后将结果mock掉,用doReturn则不走方法体,如果不用spy一般推荐thenReturn
//
when(mock.queryDomain(WEIGHT_MAP_RESET_DURATION)).thenReturn(createDuration());
doReturn(createDuration()).when(mock).queryDomain(WEIGHT_MAP_RESET_DURATION);
ResetDataController
mock = Mockito.mock(ResetDataController.class);;
// thenReturn会先走一遍方法体,然后将结果mock掉,用doReturn则不走方法体
//
when(mock.queryDomain(WEIGHT_MAP_RESET_DURATION)).thenReturn(createDuration());
Mockito.doCallRealMethod().when(mock).resetDeptCodeData(Mockito.any());
Mockito.doCallRealMethod().when(mock).checkArgs(Mockito.any());
  1. 检测方法调用次数

//1.检测mock的某个举动(方法)是否被调用过n次
Mockito.verify(mock,Mockito.times(1).description("ERROR")).queryDomain(Mockito.any());
//2.打桩 stub
when(mock.queryDomain(Mockito.any())).thenReturn(createPeak());
//3. 有返回值的方法抛异常
//when(mock.resetDeptCodeData(any())).thenThrow(new SssRuntimeException("mock error",""))
  1. powermock
    (1)参考:https://my.oschina.net/jackieyeah/blog/157076
    (2)两个重要注解
    –@RunWith(PowerMockRunner.class)
    –@PrepareForTest( { YourClassWithEgStaticMethod.class })
    当需要mock静态、 私有、final、本地方法以及当调用某各类初始化方法时需要直接返回mock对象时 需要mock,比如withNew(@PrepareForTest里写的类是需要mock的new对象代码所在的类)
    eg:
    @PowerMockIgnore(“javax.management.*”) //为了解决使用powermock后,提示classloader错误
    (3)案例:
 //添加preparefortest后可mock final 方法
@Test
public
void testFinalCall(){
MockBase base = new MockBase();
Student mock1 = when(mock(Student.class).testFinal()).thenReturn(111).getMock();
System.out.println(base.testFinal(mock1));
}
@Test
//test mock static
required PrepareForTest
public
void testStatic(){
mockStatic(MockBase.class);
when(MockBase.testStatic()).thenReturn(4444);
System.out.println(MockBase.testStatic());
}
//测试私有方法
@Test
public
void testMockPrivate() throws Exception {
MockBase mock = when(mock(MockBase.class), "testPrivate").thenReturn(5555).getMock();
when(mock.forTestPrivate()).thenCallRealMethod();
Assert.assertEquals(5555,mock.forTestPrivate());
}
//测试系统类的静态方法
@Test
public
void
testSystemStaticMethod(){
MockBase base = new MockBase();
mockStatic(System.class);
when(System.getProperty("test")).thenReturn("2b");
Assert.assertEquals("2b", base.testSystemClass());
}
//当调用new 指令时,返回一个mock对象或者抛异常
Student student0 = mock(Student.class);
whenNew(Student.class).withAnyArguments().thenReturn(student0);
Student student = base.callInternalInstance1();
System.out.println(student.getName());
Assert.assertEquals(student.name,student0.name);
  1. 同一个方法绝对不能打桩多次,可以使用自定义answer,根据不同参数返回不同结果
//todo
同一个方法绝对不能when打桩多次,以下会报各种问题,比如when中报错NPE
/*
when(paramCacheService.queryParamCacheSingle(argThat(argument -> {
System.out.println("222when打印:"+argument);
return WEIGHT_MAP_RESET_DURATION.equals(argument.getParamName());
}))).thenReturn(createDuration());
*/
/*WEIGHT_MAP_RESET_DURATION.equals(argument.getParamName()))))
.thenReturn(createDuration());*/
/*
PowerMockito.when(paramCacheService.queryParamCacheSingle(argThat(argument -> PEAK_TIME.equals(argument.getParamName()))))
.thenReturn(createPeak());*/
//使用answer根据不同参数,进行return
when(paramCacheService.queryParamCacheSingle(argThat(argument -> {
System.out.println("1111when打印:"+argument);
return argument instanceof
ParamCacheDomain;
}))).thenAnswer(new Answer<ParamCacheDomain>() {
@Override
public ParamCacheDomain answer(InvocationOnMock invocation) throws Throwable {
ParamCacheDomain domain = (ParamCacheDomain)invocation.getArguments()[0];
// 这里是关键
if(PEAK_TIME.equals(domain.getParamName())){
return
createPeak();
}
return createDuration();
}
});

14.junit测试可以通过指定@ComponentScan来进一步缩小或者扩大指定的扫描范围

可以在test目录下新建一个启动器
//excludeFilters进一步排除不需要的class
// includeFilters 加入一些没有使用spring注解的类作为bean
@ComponentScan(basePackages = {"com.sf.hwtdop.config.redis","com.sf.hwtdop.common.util"}
, excludeFilters = {@ComponentScan.Filter(type= FilterType.ASSIGNABLE_TYPE,classes = WaybillNoValidator.class)}
)
@SpringBootApplication
class HwTdopApplicationTests {
public static void main(String[] args) {
SpringApplication.run(HwTdopApplicationTests.class);
}
}
//指定测试的启动类
@SpringBootTest(classes = HwTdopApplicationTests.class)
public class RedLockTest {
@Autowired
RedissonClient redissonClient;
@Autowired
RedisLockUtil util;
@Autowired
ApplicationContext context;
@Test
public void testLock() throws InterruptedException {}
  1. mockito3.4.x+ supports to mock static final and private method
    usage:
Mockito
V3.4.x
支持 静态 final 和私有,需要inline包
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>3.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>3.9.0</version>
<scope>test</scope>
</dependency>
使用时直接调用即可,不用加注解
mockStatic(UserUtil.class);
PowerMock:不支持junit5

16.mockito使用过程中出现的问题
https://www.zhihu.com/search?type=content&q=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95

最后

以上就是等待大地为你收集整理的单元测试和MockandPowerMock的全部内容,希望文章能够帮你解决单元测试和MockandPowerMock所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部