單元測試之PowerMock


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靜態方法,有兩個前提。

  1. @PrepareForTest聲明該方法所在的該類
  2. 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));


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM