单元测试之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