PowerMock介绍
https://www.jianshu.com/p/60309d71002d

单元测试编写方法来编写单元测试的简要小教程

单元测试的最终目的是达到足够高的代码覆盖率

我们需要测试的一般为serviceimpl实现类中的方法,在该类中使用到的maven或gradle导入的第三方jar包,以及经过了他们自己的测试,我们默认他正确,不需要进行测试

我们自己编写的工具类方法,在impl中视具体情况而定,如果工具类的方法逻辑非常复杂,那么建议把工具类也写一个单元测试,然后在impl中将其mock掉,如果工具类不复杂,就可以直接在impl中调用真实工具类逻辑,完成测试

代码结构:

@Slf4j
 @PrepareForTest(value = {ShadowAppServiceImpl.class, ResultDTO.class,LambdaQueryWrapper.class, LambdaUpdateWrapper.class})
 @RunWith(PowerMockRunner.class)public class ShadowAppServiceImplTest extends BaseServiceTest {
//需要进行单测的对象
 private ShadowAppService Shadow AppService;//单测对象构造方法所需要的参数
private Shadow Mapper Shadow Mapper;
/*
还有serviceimpl中的其他的类成员也在此处定义
*/
//这两个wrapper主要对应数据库的操作,继承了BaseServiceTest之后,可用这两个wrapper去做mybatis中的增删查改
private LambdaQueryWrapper lambdaQueryWrapper;
private LambdaUpdateWrapper lambdaUpdateWrapper;
@Before
 public void setUp() throws Exception {/*
mock掉impl其中的对象,并用mock掉的对象构建出我们需要单测的实例
*/
Shadow Mapper = PowerMockito.mock(ShadowMapper.class);
 ShadowAppService = PowerMockito.spy(new ShadowAppServiceImpl(Shadow Mapper));/*
wrapper的初始化,相当于对这两个wrapper进行了mock
*/
lambdaQueryWrapper = queryLambdaPrepare(lambdaQueryWrapper);
 lambdaUpdateWrapper = updateLambdaPrepare(lambdaUpdateWrapper);/*
通过反射给类中的域进行赋值
*/
ReflectionTestUtils.setField(Shadow AppService, “ShadowMapper”, Shadow Mapper);
}

这就做好了单测的基本准备工作,mock的作用在于构造出我们难以构造的对象,我们可以给mock的对象指定对给定输入的特定输出,一般情况下impl中的对象均需要进行mock,但有些例外需要使用真实对象,比如线程池

例如:PowerMockito.when(redissonClient.getBucket(any(String.class))).thenReturn(bucket);

对于没有返回值的情况,使用 Mockito.doNothing().when(Shadow Mapper).updateByCode(any(Shadow Po.class));

通过这种方式,达到使函数朝着不同方向继续往下运行的目的

有时遇到了函数的假参数或者假返回值非常难以构造的情况,这时可以把参数或返回值也进行mock,中间层皆可mock掉,直到遇到好构造的结构为止

接下来开始编写函数的单测代码,首先要确定,哪些函数需要编写单测代码。我们只编写最顶层的函数的单测,如果一个函数被另一个函数所调用,那么他就不用编写单测,而在他被调用的情况下,你需要进入到他内部,

走他的逻辑。

然后要确定函数的多个分支涉及到的不同情况应该如何处理,有的时候可以用同一个单测代码对应不同的测试用例来覆盖到多分支,有的时候需要人为mock不同的假参数和假返回值来覆盖不同分支,这些需要在编写的时候

考虑清晰,才能做到全部覆盖。

对于难以构造的dto,比如层数很多需要逐层构造的,可以使用从resources中读取json文件的方法进行构造,这样只需要复制粘贴修改里面的值即可完成新对象的创建

异常状态的代码我们也需要覆盖到,通过构造数据手动的触发异常,然后利用try catch进行捕获,即可覆盖到异常的代码