单元测试之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));
posted @ 2020-11-01 23:57  kancy  阅读(2454)  评论(1编辑  收藏  举报