PowerMock教程

时间:2020-02-23 14:35:30  来源:igfitidea点击:

1.概述

Mockito是一个强大的、开源的Java模拟框架。它为单元测试提供的特性不可避免地是独特的和重要的,尽管如此,在编写单元测试用例时,它为开发人员减轻了许多工作。
虽然Mockito可以帮助几乎所有的事情,但有些事情它不能做。比如存根或测试私有、final或静态方法。为这些方法编写测试用例需要更多的能力,这通常会导致开发人员为这些方法编写繁琐的代码。
在这里,PowerMockito来救援。PowerMockito能够测试私有、最终或静态方法,因为它使用Java反射API。在我们研究它的用途时,让我们看看实际的演示。

2.创建一个简单的Java Maven项目。

3.使用Maven添加依赖项

正如我们之前谈过的那样,Mockito或者PowerMockito开始的最佳方式是找到它的Maven依赖关系并将其添加到我们的项目中。
以下是我们需要添加的依赖项:

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.6.4</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito</artifactId>
    <version>1.6.4</version>
    <scope>test</scope>
</dependency>

现在我们正在添加依赖项,让我们在测试中使用注释。

pom.xml如下所示:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.igi.theitroad</groupId>
	<artifactId>PowerMockitoExample</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<dependency>
			<groupId>org.powermock</groupId>
			<artifactId>powermock-module-junit4</artifactId>
			<version>1.6.4</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.powermock</groupId>
			<artifactId>powermock-api-mockito</artifactId>
			<version>1.6.4</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

4.启用PowerMock注释

就像我们对Mockito所需的一样,我们还需要使用PowerMockito使用注释。
像Mockito一样,我们利用类似的注释,如图所示:

import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
 
@RunWith(PowerMockRunner.class)
@PrepareForTest(fullyQualifiedNames = "org.igi.theitroad.*")
public class PowerTest {
 
    ...
}

让我们看看我们上面使用的每个注释:

  • @runwith注释类似于我们在模仿中所做的事情。我们将在测试中使用PowerMockRunner使用PowermockRunner,而不是使用Mockito。
  • @preparefortest是一个完全预定的name包,带有通配符。这通知PowerMockito程序准备Java Reflection API进行测试。

5.Mocking最终方法

让我们开始使用PowerMockito API来通过模拟最终方法。
要模拟最终方法,并不多令人惊讶,我们应该首先定义最终方法。
这是我们将测试的模型的示例:

package org.igi.theitroad.model;
 
public class ClassWithFinalMethods {
 
    public final String printMessage(String message) {
        return message;
    }
}

简单,该方法只返回传递给它的字符串。
现在,现在是时候写下测试了:

package org.igi.theitroad.powermock;
 
import org.igi.theitroad.model.ClassWithFinalMethods;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
 
@RunWith(PowerMockRunner.class)
@PrepareForTest(fullyQualifiedNames = "org.igi.theitroad.*")
public class PowerMockFinalMethodTest
{
	@Test
	public void testClassWithFinalMethods_printMessage_finalMethod() throws Exception {
	 
	    String message = "Hello PowerMockito"; //1
	 
	    ClassWithFinalMethods mockObject = PowerMockito.mock(ClassWithFinalMethods.class); //2
	    PowerMockito.whenNew(ClassWithFinalMethods.class).withNoArguments().thenReturn(mockObject); //3
	 
	    ClassWithFinalMethods object = new ClassWithFinalMethods(); //4
	    PowerMockito.verifyNew(ClassWithFinalMethods.class).withNoArguments(); //5
	 
	    PowerMockito.when(object.printMessage(message)).thenReturn(message); //6
	    String helloPowerMockito = object.printMessage(message); //7
	    Mockito.verify(object).printMessage(message); //8
	    Assert.assertEquals(message, helloPowerMockito); //9
	}
}

我们使用方法使用类名,以便在导入类时不会发生混淆。
让我们解释在上面的测试中发生的整个很多:

  • 我们定义了一个通用字符串消息,我们将使用作为参数和期望。
  • 我们嘲笑正在测试的系统的实例,classwithfinalmethods。
  • 当new()方法确保每当通过调用no参数构造函数使用新关键字进行此类的实例时,返回此模拟实例而不是实际对象。
  • 我们调用无参数构造函数来制作被测系统的实例。
  • 我们验证了在最后一步中实际涉及的任何参数构造函数。
  • 当调用最终方法时,我们使用步骤1中定义的字符串设置了一个预期的字符串。
  • 调用最终方法PrintMessage(...)。
  • 我们验证了最终的方法是否实际调用。
  • 最后,我们将我们的期望视为返回给我们的实际字符串。

现在实际上很多。
我们使用了一个简单的例子,使一切都有意义。
正如我们用静态方法明确地使用类名,就像使用此测试即可运行。

我们现在通过最终方法。
现在是时候了解如何用Powermockito测试静态方法。
我们使名为ClassWithStaticMethod的新类并添加新方法,它是静态的:

package org.igi.theitroad.model;
 
public class ClassWithStaticMethod {
 
    public static String printMessage(String message) {
        return message;
    }
}

类似的方法如前所述,该方法刚刚返回传递给它的字符串。
现在,现在是时候写下测试了:

package org.igi.theitroad.powermock;
 
import org.igi.theitroad.model.ClassWithStaticMethod;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
 
@RunWith(PowerMockRunner.class)
@PrepareForTest(fullyQualifiedNames = "org.igi.theitroad.*")
public class PowerMockStaticMethodTest
{
	@Test
	public void testClassWithStaticMethod_printMessage_staticMethod() {
 
	    String message = "Hello PowerMockito"; //1
	    String expectation = "Expectation"; //2
 
	    PowerMockito.mockStatic(ClassWithStaticMethod.class); //3
	    PowerMockito.when(ClassWithStaticMethod.printMessage(message)).thenReturn(expectation); //4
 
	    String actual = ClassWithStaticMethod.printMessage(message); //5
	    Assert.assertEquals(expectation, actual); //6
	}
}

该测试小于前面。
让我们谈谈我们在此进行的每一步:

  • 我们定义了一个通用字符串消息,我们将使用作为参数。
  • 另一个通用字符串消息,用作期望。
  • 准备ClassWithStaticMethod进行静态方法测试。
  • 在调用静态方法时准备期望。
  • 调用静态方法。
  • 验证预期和实际结果。

实际上测试静态方法非常简单。
关键部分是调用powermockito.mockstatic(...),以便为类启用PowerMockito API。

在最后一个位,在本节中,我们将测试私有方法。
这是Java中反射API的另一个令人敬畏的使用。
首先,我们定义了我们的测试系统:

package org.igi.theitroad.model;
 
public class ClassWithPrivateMethods {
 
    private String printMessage(String message) {
        return message;
    }
 
    public String privateCall(String message) {
        return printMessage(message);
    }
}

现在,定义内部调用私信的公共消息是必要的。
让我们看看我们的测试,看看它是如何利用反射API的考验:

package org.igi.theitroad.powermock;
 
import org.igi.theitroad.model.ClassWithPrivateMethods;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
 
@RunWith(PowerMockRunner.class)
@PrepareForTest(fullyQualifiedNames = "org.igi.theitroad.*")
public class PowerMockPrivateMethodTest
{
	@Test
	public void testClassWithPrivateMethods_printMessage_privateMethod() throws Exception {
 
	    String message = "Hello PowerMockito";
	    String expectation = "Expectation";
 
	    ClassWithPrivateMethods mock = PowerMockito.spy(new ClassWithPrivateMethods());
	    PowerMockito.doReturn(expectation).when(mock, "printMessage", message);
 
	    String actual = mock.privateCall(message);
	    Assert.assertEquals(expectation, actual);
	}
}

其中,需要指出的是:

  • 我们首先使用powermockito.spy(...)方法创建模拟。
  • 接下来,我们通过将方法名称作为字符串参数提供给(...)方法来使用反射API。
  • 最后,我们调用公共方法,又调用私有方法,并使用Assertequals(...)方法验证我们的结果。