PowerMockito单元测试总结

1. 什么是单元测试?

  • 单元测试是指,对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,这里的最小可测试单元通常是指函数或者类。
  • 单元测试都是以自动化的方式执行,所以在大量回归测试的场景下更能带来高收益。
  • 单元测试代码里提供函数的使用示例,因为单元测试的具体表现形式就是对函数以各种不同输入参数组合进行调用。

2. 为什么要使用MOCK?

  • 在做单元测试的时候,我们会发现我们要测试的方法会引用很多外部依赖的对象,比如:(发送邮件,网络通讯,远程服务, 文件系统等等)。 而我们没法控制这些外部依赖的对象,为了解决这个问题,我们就需要用到Mock工具来模拟这些外部依赖的对象,来完成单元测试。

3. 为什么要使用PowerMock?什么是PowerMock?

  • 比较流行的Mock工具如jMock 、EasyMock 、Mockito等都有一个共同的缺点:不能mock静态、final、私有方法等。而PowerMock能够完美的弥补以上三个Mock工具的不足。
  • PowerMock是一个扩展了其它如EasyMock等mock框架的、功能更加强大的框架。PowerMock使用一个自定义类加载器和字节码操作来模拟静态方法,构造函数,final类和方法,私有方法,去除静态初始化器等等。通过使用自定义的类加载器,简化采用的IDE或持续集成服务器不需要做任何改变。熟悉PowerMock支持的mock框架的开发人员会发现PowerMock很容易使用,因为对于静态方法和构造器来说,整个的期望API是一样的。PowerMock旨在用少量的方法和注解扩展现有的API来实现额外的功能。目前PowerMock支持EasyMock和Mockito。

4. 如何使用PowerMock?

4.1 maven依赖

	<dependency>   
        <groupId>org.powermockgroupId>   
        <artifactId>powermock-module-junit4artifactId>   
        <version>1.6.5version>   
        <scope>testscope>   
     dependency>   
     <dependency>   
        <groupId>org.powermockgroupId>   
        <artifactId>powermock-api-mockitoartifactId>   
        <version>1.6.5version>   
        <scope>testscope>   
     dependency>   
     <dependency>
  	    <groupId>org.mockitogroupId>
  	    <artifactId>mockito-coreartifactId>
  	    <version>1.10.19version>
  	    <scope>testscope>
  	dependency>

4.2 注解

  • @RunWith(PowerMockRunner.class)
    @Runwith 是一个运行器
    @RunWith(PowerMockRunner.class) 是指用PowerMockRunner来运行
  • @PrepareForTest( {YourClass.class })
    @PrepareForTest( {YourClass.class }) 的值是被MOCK的静态方法,私有方法,或者是PowerMockito.whenNew()的被注入类
  • @InjectMocks
    创建一个实例,简单的说是这个Mock可以调用真实代码的方法,其余用@Mock(或@Spy)注解创建的mock将被注入到用该实例中
  • @Spy
    对函数的调用均执行真正部分
  • @Mock
    对函数的调用均执行mock(即虚假函数),不执行真正部分

4.3 用法

4.3.1 Mock数据库Dao层返回
//返回值可以自己定义
PowerMockito.when(faceCollectMapper.qryFaceAttachInfo(Mockito.anyObject())).thenReturn(attachInfo);
//方法调用多次,且返回值不同
PowerMockito.when(jdbcTemplate.batchUpdate(Mockito.anyObject())).thenReturn(arr).thenReturn(arr).thenThrow(new IllegalArgumentException("参数缺失"));
4.3.2 Mock静态方法
记得要在@PrepareForTest注解后面加静态方法类
//先mock静态方法类,再mock调用方法返回值
PowerMockito.mockStatic(ServiceClient.class);
PowerMockito.when(ServiceClient.CallService(Mockito.anyObject())).thenReturn(json1);
4.3.3 Mock BindingResult入参校验异常
@Mock
private BindingResult bindingResult;
@Test
public void test(){
PowerMockito.when(bindingResult.hasErrors()).thenReturn(true);
FieldError fieldError = PowerMockito.mock(FieldError.class);
PowerMockito.when(bindingResult.getFieldError()).thenReturn(fieldError);
PowerMockito.when(fieldError.getDefaultMessage()).thenReturn("参数缺失");
}
4.3.4 Mock 异常抛出
//两种方法
PowerMockito.doThrow(new IllegalArgumentException("Error Message")).when(busiPromoteMapper).getSeq();
PowerMockito.when(jdbcTemplate.batchUpdate(Mockito.anyObject())).thenThrow(new IllegalArgumentException("Error Message"));
4.3.5 Mock文件、流等(构造方法)
记得要在@PrepareForTest注解后面加被注入类(被测试类,不是File)
//Mock文件、流等
File file =  Mockito.mock(File.class);
FileInputStream fin =  Mockito.mock(FileInputStream.class);
//参数传入使用Mock数据的入参进行注入
PowerMockito.whenNew(File.class).withArguments("10011001").thenReturn(file);
PowerMockito.whenNew(FileInputStream.class).withArguments(file).thenReturn(fin);
PowerMockito.when(fin.available()).thenReturn(3816);
PowerMockito.when(file.exists()).thenReturn(true);
4.3.6 Mock Private Method
 @Test
 public void testMockPrivateMethodWithStub() throws Exception {
     Student student = new Student();
     String mockPrivateMethod = "mockPrivateMethod";
     PowerMockito.stub(MemberMatcher.method(Student.class, "getPrivateMethod")).toReturn(mockPrivateMethod);
     assertThat(student.callPrivateMethod(), is(mockPrivateMethod));
 }
4.3.7 Mock Enum
 @Test
 public void testMockEnum(){
     PersonType personType = PowerMockito.mock(PersonType.class);
     Whitebox.setInternalState(PersonType.class, "N", personType);
     when(personType.getType()).thenReturn("mockN");

     assertThat(PersonType.N.getType(), is("mockN"));
     assertThat(PersonType.S.getType(), is("student"));
 }
4.3.8 Mock Serclet调用 httpServletRequest httpServletResponse
注:这个不是使用PowerMockito,但是这里一并总结了
maven依赖
<dependency>
	<groupId>org.springframeworkgroupId>
	<artifactId>spring-mockartifactId>
	<version>1.1version>
dependency>
写法
//MOCK httpServletRequest
//创建Mock对象
MockHttpServletRequest request = new MockHttpServletRequest();
//创建Mock对象
MockHttpServletResponse response = new MockHttpServletResponse();
//设置流的内容
request.setContent(reqStr.getBytes());

参考

https://github.com/powermock/powermock/wiki/Mockito
https://blog.csdn.net/qisibajie/article/details/79068086

总结

对于阿拉盯项目中的单元测试总结就到这里,应该可以覆盖项目中的大部分代码。有什么错误或者补充还请大家可以告知。

你可能感兴趣的:(单元测试,java,spring,boot)