PowerMockito

PowerMock is a Java framework that allows you to unit test code normally regarded as untestable.

PowerMock是一个Java框架,它允许您对通常认为不可测试的代码进行单元测试。

PowerMock是一个框架,它扩展了EasyMock等其他模拟库,具有更强大的功能。PowerMock使用自定义的类加载器和字节码操作来模拟静态方法、构造函数、final类和方法、私有方法、删除静态初始化器等等。通过使用自定义类加载器,无需对IDE或持续集成服务器进行任何更改,从而简化了采用。熟悉所支持的模拟框架的开发人员会发现PowerMock很容易使用,因为对于静态方法和构造函数来说,整个期望API都是一样的。PowerMock的目标是通过少量的方法和注释来扩展现有的API,以支持额外的特性。目前PowerMock支持EasyMock和Mockito。

在编写单元测试时,绕过封装通常很有用,因此PowerMock包含了几个简化反射的特性,这些特性对测试特别有用。这样可以方便地访问内部状态,但也简化了部分和私有mocking。

github:https://github.com/powermock/powermock/wiki/Mockito#partial-mocking

请注意,PowerMock主要面向具有单元测试方面的专家。把它交到初级开发人员手中可能弊大于利。

  1. PowerMock1,227 usages

org.powermock » powermock-api-mockito2Apache

PowerMock API for Mockito 2.+..

  1. PowerMock3,422 usages

org.powermock » powermock-module-junit4Apache

PowerMock support module for JUnit 4.x.

Last Release on Mar 30, 2020

  1. PowerMock98 usages

org.powermock » powermock-module-junit4-rule-agentApache

PowerMock support module for JUnit 4.x rules with Java agent

Last Release on Mar 30, 2020

  1. PowerMock112 usages

org.powermock » powermock-classloading-xstreamApache

Performs classloader deep-cloning using X-Stream.

Last Release on Mar 30, 2020

Maven setup for the Mockito 2.x

需要3和1.

Need to combine PowerMock with another JUnit runner?

当使用PowerMock的whenNew方法时,@PrepareForTest里写的类是需要mock的对象代码所在的类

testImplementation testImplementation 'junit:junit:4.+'

// https://mvnrepository.com/artifact/org.mockito/mockito-core
testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.1.0'

testImplementation 'org.powermock:powermock-core:2.0.5'
testImplementation group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.5'
testImplementation group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.5'
testImplementation "org.powermock:powermock-module-junit4-rule:2.0.5"
testImplementation group: 'org.powermock', name: 'powermock-module-junit4-rule-agent', version: '2.0.5'
testImplementation group: 'org.powermock', name: 'powermock-classloading-xstream', version: '2.0.5'
testImplementation 'org.assertj:assertj-core:3.11.1'

pwermock final方法

  1. 测试类上添加注解@RunWith(PowerMockRunner.class)

  2. @PrepareForTest(final方法所在的类.class)

  3. final void方法 用Mockito.verify验证调用次数 ,PowerMockito没有verify方法

    @Test
    public void saveFinal() {
        Mockito.doNothing().when(userDao).saveFinal(user);
        userService.saveFinal(user);
        Mockito.verify(userDao,Mockito.times(1)).saveFinal(user);
    }
  4. final 有返回值的 用Powermockito或者Mockito.when都可以

    因为Powermockito.when()也是去调Mockito.when

    @Test
    public void queryFinal() {
        PowerMockito.when(userDao.queryFinal("name")).thenReturn(user);
        assertEquals(user,userService.queryFinal("name"));
    }
  5. final类 的对象如何Mock?

    只需
    1.@PrepareForTest({final.class}
    2.Mock注解在测试类中final类的成员的声明

powermock new关键字

比如要测A类,A类中的new 关键字 不能用Powermock,得其他类的new 才可以

  @Override
    public Node getLocalNode(int num, String name) {
        return new Node(num,name);
    }

//mock  new关键字
@Test
@PrepareForTest(LocalServiceImpl.class) //必须要这句:PrepareForTest修改local类的字节码以覆盖new的功能
public void testNew() throws Exception{
    Node target = new Node(1,"target");

//ArgumentMatchers.eq(***)
    PowerMockito.whenNew(Node.class).withArguments(anyInt(),eq("name")).thenReturn(target);

    Node result = localService.getLocalNode(2,"name");
    assertEquals(target,result);
    assertEquals(1,result.getNum());
    assertEquals("target",result.getName());

    Node result2 = localService.getLocalNode(1,"test");
    assertNull(result2);
    
}
How to verify construction of new objects

Use PowerMockito.verifyNew, e.g.

verifyNew(MyClass.class).withverifyNew(MyClass.class).withNoArguments();

静态方法抛异常

PowerMockito.when(Base64.decode(anyString(), anyInt())).thenThrow(PowerMockito.when(Base64.decode(anyString(), anyInt())).thenThrow(new IllegalArgumentException());

powermock 静态方法

1.powermock .mockStatic(UserDao.class)

2.@PrepareForTest(静态方法所在的类.class)

3.静态void方法 校验:先调用业务方法,然后验证次数,最后再调用要mock的静态void方法

@Test
public void saveStatic() {
    PowerMockito.mockStatic(UserDao.class);
    userService.saveStatic();
    PowerMockito.verifyStatic(UserDao.class,Mockito.times(1));
    UserDao.saveStatic();
}

4.静态有返回值方法

@Test
public void query() {
    PowerMockito.mockStatic(UserDao.class);
    Mockito.when(UserDao.query()).thenReturn(user);
    assertEquals(user,userService.query());
}
A full example for mocking, stubbing & verifying static method
@RunWith(PowerMockRunner.@RunWith(PowerMockRunner.class)
@PrepareForTest(Static.class)
public class YourTestCase {
    @Test
    public void testMethodThatCallsStaticMethod() {
        // mock all the static methods in a class called "Static"
        PowerMockito.mockStatic(Static.class);
        // use Mockito to set up your expectation
        Mockito.when(Static.firstStaticMethod(param)).thenReturn(value);
        Mockito.when(Static.secondStaticMethod()).thenReturn(123);

        // execute your test
        classCallStaticMethodObj.execute();

        // Different from Mockito, always use PowerMockito.verifyStatic(Class) first
        // to start verifying behavior
        PowerMockito.verifyStatic(Static.class, Mockito.times(2));
        // IMPORTANT:  Call the static method you want to verify
        Static.firstStaticMethod(param);


        // IMPORTANT: You need to call verifyStatic(Class) per method verification,
        // so call verifyStatic(Class) again
        PowerMockito.verifyStatic(Static.class); // default times is once
        // Again call the static method which is being verified
        Static.secondStaticMethod();

        // Again, remember to call verifyStatic(Class)
        PowerMockito.verifyStatic(Static.class, Mockito.never());
        // And again call the static method.
        Static.thirdStaticMethod();
    }
}

5.静态方法doNothing

powermock private方法

//1.有public方法会调用它
How to verify private behavior

Use PowerMockito.verifyPrivate(), e.g.

verifyPrivate(tested).invoke(verifyPrivate(tested).invoke("privateMethodName", argument1);

This also works for private static methods.

@RunWith(PowerMockRunner.@RunWith(PowerMockRunner.class)
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods
@PrepareForTest(PartialMockClass.class)
public class YourTestCase {
    @Test
    public void privatePartialMockingWithPowerMock() {        
        PartialMockClass classUnderTest = PowerMockito.spy(new PartialMockClass());

        // use PowerMockito to set up your expectation
        PowerMockito.doReturn(value).when(classUnderTest, "methodToMock", "parameter1");

        // execute your test
        classUnderTest.execute();

        // Use PowerMockito.verify() to verify result
        PowerMockito.verifyPrivate(classUnderTest, times(2)).invoke("methodToMock", "parameter1");
    }
}

PowerMockIgnore??

powermock 能用@InjectMock吗?

可以

PowerMock踩坑指南

  • 可以用@InjecteMock

  • 没有用到的对象 不要加进去

  • 测试类,他实现的接口可以不用写在preparefortest中

powermock : new关键字, private方法, final 方法 ,static方法,系统类的静态方法

Whitebox.getInternalState?

PowerMock知识点掌握

单测用例编写过程中,熟练程度一部分完全取决于对单测工具框架的了解程度,这块没捷径可走,必须要掌握清楚明白,简单列一下其知识点,具体还是需要自己去搜索资料掌握的。

(1)PowerMock注解@RunWith与@PrepareForTest的使用;

(2)测试或模拟static方法;

(3)测试或模拟返回void的静态方法;

(4)PowerMockito.doNothing与PowerMockito.doThrow的使用;

(5)如何验证方法调用;

(6)如何验证调用次数的方法;

(7)测试或模拟final类或方法;

(8)测试或模拟构造方法;

(9)如何做参数匹配;

(10)Answer接口的使用;

(11)如何使用spy进行部分模拟;

(12)如何测试或模拟私有方法;

(13)@Before和@Test的作用;

(14)如何给私有的字段赋值;

(15)如何模拟异常。

https://blog.csdn.net/tmq1225/article/details/72770537

mock和spy对象的区别是mock对象对于未指定处理规则的调用会按方法返回值类型返回该类型的默认值(如int、long则返回0,boolean则返回false,对象则返回null,void则什么都不做),而spy对象在未指定处理规则时则会直接调用真实方法。

powermock final类

调用mockito的对象的void方法 : 会调用1次,什么都不做

这样验证。Mockito.verify(finalClass,Mockito.times(1)).test1();

调用mockito的对象的有返回值的方法 ,返回值是基本类型

调用mockito的对象的有返回值的方法 ,返回值是引用类型

校验

PowerMockito.verifyPowerMockito.verifyNoMoreInteractions();  与预期不符合 ,先不使用。
可使用Mockito.verify校验对象实例的
静态的不行

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!