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));
