PowerMock是一个Java模拟框架,用于解决测试问题。
举个例子,你在使用Junit进行单元测试时,并不想让测试数据进入数据库,怎么办?这个时候就可以使用PowerMock,拦截数据库操作,并模拟返回参数。
Quick Start
1.引入maven依赖
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>2.0.4</version>
<scope>test</scope>
</dependency>
2.一个简单的例子
@RunWith
告诉JUnit使用PowerMockRunner
进行测试@PrepareForTest
所有需要测试的类列在此处,适用于模拟final类或有final
,private
,static
,native
方法的类,,例如:@PrepareForTest({RandomUtil.class})
@PowerMockIgnore
为了解决使用powermock后,提示classloader错误,例如:@PowerMockIgnore("javax.management.*")
@InjectMocks
自动将@Mock注解的对象注入进来@InjectMocks
注释的对象@Mock
声明对象是一个Mock对象,也可以使用PowerMockito.mock(UserService.class)
,但无法被自动注入。
/**
* PowerMockTests
*
* @author kancy
* @date 2020/11/1 22:26
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({UserThreadLocalUtil.class})
@PowerMockIgnore
public class PowerMockTests {
@InjectMocks
private UserController userController;
@Mock
private UserService userService;
@Test
public void queryUserTest(){
Long userId = 1L;
User user = new User();
// mock , 当调用userService.findById()方法时,返回user对象
PowerMockito.when(userService).findById(any()).thenReturn(user);
User queryUser = userController.queryUser(userId);
Assert.assertEquals(queryUser, user);
}
}
3.Mock静态方法
mock静态方法,有两个前提。
@PrepareForTest
声明该方法所在的该类PowerMockito.mockStatic(UserThreadLocalUtil.class)
声明
/**
* PowerMockTests
*
* @author kancy
* @date 2020/11/1 22:26
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({UserThreadLocalUtil.class})
public class UserThreadLocalUtilTests {
@Test
public void getUserIdTest(){
Long userId = 1L;
PowerMockito.mockStatic(UserThreadLocalUtil.class);
PowerMockito.when(UserThreadLocalUtil.getUserId()).thenReturn(userId);
Assert.assertEquals(userId, UserThreadLocalUtil.getUserId());
}
}
Spy功能
Spy很少用,但是也极其强大,有的时候,例如有两个静态方法或者实例,如果我只想mock其中之一,这个时候Spy就该上场了。它的强大之处就在于可以部分mock。
UserService userService = PowerMockito.spy(new UserService());
PowerMockito.doNothing().when(userService).printUser1(any());
// printUser1被mock了,所以不会打印User。
userService.printUser1(new User());
// 如果是spy,printUser2没有mock了,则会按照真实的方法执行会打印User,使用mock则会被拦截。
userService.printUser2(new User());
其他案例
1.mock无返回值的方法
PowerMockito.doNothing().when(userService).deleteUser(any());
2.mock有返回值的方法
PowerMockito.doReturn(new User()).when(userService.queryUser(eq(1L)));
PowerMockito.when(userService.queryUser(anyLong())).thenReturn(new User());
3.mock方法执行异常
PowerMockito.doThrow(new RuntimeException()).when(userService.queryUser(any()));
PowerMockito.when(userService.queryUser(any())).thenThrow(new RuntimeException());
4.mock构造方法
PowerMockito.whenNew(File.class).withAnyArguments().thenReturn(new File("/test"));
PowerMockito.whenNew(UserService.class).withNoArguments().thenReturn(new UserService());
5.mock静态方法
PowerMockito.mockStatic(StringUtils.class);
PowerMockito.doReturn(true).when(StringUtils.hasText(anyString()));
6.mock私有方法
PowerMockito.doNothing().when(userService, "printUser", any(User.class));