Java测试框架系列:PowerMock使用系列-7:和Mockito一起使用PowerMock

本文介绍了如何在Java测试中将PowerMock与Mockito结合使用,包括Mock静态方法、部分Mock、验证行为和private行为,以及如何配置Maven项目。提供了详细用法示例和注意事项。

和Mockito一起使用PowerMock

(源码加我QQ3177181324)

介绍

事实上,PowerMock提供了一个名为“PowerMockito”的类,用于创建mock对象/类并开始验证和期望(一个行为/调用或者返回值),您仍然可以使用Mockito设置和验证期望的所有其他内容(例如times(),anyInt())。

所有的用法需要@RunWith(PowerMockRunner.class),并在类上标识@PrepareForTest注解。

支持版本

PowerMock 2.0.0及更高版本具有Mockito 2的支持。

PowerMock 1.7.0及更高版本具有Mockito 2的实验性支持。

许多问题仍未解决。PowerMock使用Mockito 内部API,但至少可以同时使用两个模拟框架。

MockitoPowerMock
2.8.9+2.x
2.8.0-2.8.91.7.x
2.7.51.7.0RC4
2.4.01.7.0RC2
2.0.0-beta - 2.0.42-beta1.6.5-1.7.0RC
1.10.8 - 1.10.x1.6.2 - 2.0
1.9.5-rc1 - 1.9.51.5.0 - 1.5.6
1.9.0-rc1 & 1.9.01.4.10 - 1.4.12
1.8.51.3.9 - 1.4.9
1.8.41.3.7 & 1.3.8
1.8.31.3.6
1.8.1 & 1.8.21.3.5
1.81.3
1.71.2.5

Maven配置

JUnit

  • Mockito JUnit Maven配置
  • Mockito2 JUnit Maven配置

TestNG

  • Mockito TestNG Maven配置
  • Mockito2 TestNG Maven配置

用法

在下面的示例中,为了更好地了解方法的位置,我们在Mockito或PowerMockito API中未对方法使用静态导入。但是,我们强烈建议您在实际的测试用例中静态导入方法,以提高可读性。

注意:Mockito团队在Mockito 2.1.0中增加了模拟final类/方法的能力。自PowerMock 1.7.0(经过Mockito 2.8.9测试)以来,PowerMock支持此功能。可以使用PowerMock Configuration启用该功能。如果使用Mockito 2,建议使用Mockito模拟final方法/类。

Mock静态方法

如何模拟(mock)和存根(stub):

  1. 在类上添加 @PrepareForTest
@PrepareForTest(Static.class) // Static.class contains static methods
  1. 调用PowerMockito.mockStatic()以Mock静态类(用PowerMockito.spy(class)mock特定方法):
PowerMockito.mockStatic(Static.class);
  1. 只需使用Mockito.when()来设置您的期望:
Mockito.when(Static.firstStaticMethod(param)).thenReturn(value);

注意:如果需要模拟java系统类加载器/bootstrap类加载器(在java.lang或java.net等中定义的类)加载的类,则需要使用此方法。

如何验证行为

静态方法的验证分两个步骤进行。

  1. 首先调用PowerMockito.verifyStatic(Static.class) 以开始验证行为,然后
  2. 调用的静态方法Static.class进行验证。例如:
PowerMockito.verifyStatic(Static.class); // 1
Static.firstStaticMethod(param); // 2

重要提示:您需要按方法逐个调用verifyStatic(Static.class)验证。

如何使用参数匹配器

Mockito匹配器可能仍适用于PowerMock mock。例如,对每个mock的静态方法使用自定义参数匹配器:

PowerMockito.verifyStatic(Static.class);
Static.thirdStaticMethod(Mockito.anyInt());

如何验证确切的调用次数

您仍然可以将Mockito.VerificationMode(例如Mockito.times(x))与PowerMockito.verifyStatic(Static.class, Mockito.times(2))结合使用:

PowerMockito.verifyStatic(Static.class, Mockito.times(1));

如何将静态void方法存根以引发异常

如果不是私有方法:

PowerMockito.doThrow(new ArrayStoreException("Mock error")).when(StaticService.class);
StaticService.executeMethod();

请注意,您可以对final类/final方法执行相同的操作:

PowerMockito.doThrow(new ArrayStoreException("Mock error")).when(myFinalMock).myFinalMethod();

对于私有方法,请使用PowerMockito.when,例如:

when(tested, "methodToExpect", argument).thenReturn(myReturnValue);

Mock,存根和验证静态方法的完整示例

@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();
    }
}

部分Mock

您可以通过使用PowerMockito的PowerMockito.spy部分mock方法。请注意(以下内容取自Mockito文档,同样适用于PowerMockito):有时,无法使用标准when(..)方法对spy()进行打桩(stubbing,存根)。例如:

List list = new LinkedList();
List spy = spy(list);
//这样是不行的:真正的方法spy.get(0)会被调用并抛出IndexOutOfBoundsException异常(这个list仍然是空的)
//when(spy.get(0)).thenReturn("foo");

//你需要用 doReturn() 去打桩
doReturn("foo").when(spy).get(0);

如何验证行为

只需使用Mockito.vertify()进行标准验证:

Mockito.verify(mockObj, times(2)).methodToMock();

如何验证private行为

使用PowerMockito.verifyPrivate(),例如

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

这也适用于私有静态方法。

如何mock新对象的构造

使用PowerMockito.whenNew,例如

whenNew(MyClass.class).withNoArguments().thenThrow(new IOException("error message"));

请注意,您必须准备在测试过程中的用于创建MyClass新实例中的类,而不是其MyClass本身。例如,如果正在执行的类称为X,则必须先进行操作@PrepareForTest(X.class)才能使whenNew工作:

@RunWith(PowerMockRunner.class)
@PrepareForTest(X.class)
public class XTest {
  	@Test
  	public void test() {
      	whenNew(MyClass.class).withNoArguments().thenThrow(new IOException("error message"));

      	X x = new X();
      	x.y(); // y is the method doing "new MyClass()"

      	..
    }
}

如何验证新对象的构造

使用PowerMockito.verifyNew,例如

verifyNew(MyClass.class).withNoArguments();

如何使用参数匹配器

如何使用参数匹配器mock:

Mockito.verify(mockObj).methodToMock(Mockito.anyInt());  

Spy的完整示例

@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 spyingWithPowerMock() {        
        PartialMockClass classUnderTest = PowerMockito.spy(new PartialMockClass());

        // use Mockito to set up your expectation
        Mockito.when(classUnderTest.methodToMock()).thenReturn(value);

        // execute your test
        classUnderTest.execute();

        // Use Mockito.verify() to verify result
        Mockito.verify(mockObj, times(2)).methodToMock();
    }
}

私有方法部分mock的完整示例

(在PowerMock版本1.3.6+中可用)

@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");
    }
}

Mockito mock-maker-inline

在PowerMock版本1.7.0中可用

Mockito团队在Mockito 2.1.0中增加了对final类/方法进行mock的支持。通过在src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker中添加包含以下一行的文件,可以在PowerMock中启用此功能 :

mock-maker-inline
复制代码

PowerMock实现了自己的MockMaker,这导致与Mockito的mock-maker-inline不兼容,即使PowerMock只是作为依赖添加而未使用。如果在类路径中存在两个org.mockito.plugins.MockMaker,则只能使用其中一个,但不确定是哪一个。

但是PowerMock可以将调用委托给另一个MockMaker,因此无需PowerMock即可运行测试。从PowerMock 1.7.0开始,可以使用PowerMock Configuration进行配置 。

MockMaker可以通过创建org/powermock/extensions/configuration.properties文件来配置和设置:

mockito.mock-maker-class=mock-maker-inline
复制代码

将Mockitomock-maker-inline与PowerMock结合使用的示例: github.com/powermock/p…

如果觉得文章对你有帮助,麻烦 点赞、评论、收藏 你的支持是我最大的动力!!!
然后小编在学习过程中整理了一些学习资料,需要的可以加入我的学习交流群323432957 或加微dingyu-002即可免费获取Python自动化测开及Java自动化测开学习资料(里面有功能测试、性能测试、python自动化、java自动化、测试开发、接口测试、APP测试等多个知识点的架构资料) 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值