一、介绍

PowerMockito 可以用来 Mock 掉 final 方法(变量)、静态方法(变量)、私有方法(变量)。想要使用 PowerMockito Mock掉这些内容,需要在编写的测试类上使用 注解:@RunWith(PowerMockRunner.class) 及 @PrepareForTest({First.class,Second.class}),对于注解 @PrepareForTest 网上有介绍说,可以不用注解到测试类上,直接注解到测试方法上,但是我在使用的时候不知道为什么不行,仅能注解到测试方法上。

二、调用别的类中的静态方法

(1) Mock 掉静态方法

Mock 掉静态方法,需要在测试类上使用 @RunWith 及 @PrepareForTest 并 使用PowerMockito.mockStatic方法。

例子:

  1. import java.io.File;
  2.  
  3. import org.apache.commons.io.FileUtils;
  4. import org.apache.commons.lang3.StringUtils;
  5.  
  6. public class FileUtil extends FileUtils{
  7.  
  8. private static final String FILE_EXTEND_SPLIT = ".";
  9. /***文件分割符****/
  10. public static final String FILE_SEPARATOR = "/";
  11.  
  12. /**
  13. * 获取文件名(没有扩展内容)
  14. * @param fileName 文件名称
  15. * @return
  16. */
  17. public static String getNameNoExtend(String fileName){
  18. if(StringUtils.isNotBlank(fileName)){
  19. String name = fileName;
  20. int fileExtendSplitIndex = name.lastIndexOf(FILE_EXTEND_SPLIT);
  21. if(- != fileExtendSplitIndex && fileExtendSplitIndex != name.length()-){
  22. name = name.substring(, fileExtendSplitIndex);
  23. }
  24. return name;
  25. }
  26. return StringUtils.EMPTY;
  27. }
  28.  
  29. /**
  30. * 判断文件是否是目录
  31. * @param file
  32. * @return
  33. */
  34. public static boolean isDirectory(File file){
  35. if(isExist(file) && file.isDirectory()){
  36. return true;
  37. }
  38. return false;
  39. }
  40.  
  41. /**
  42. * 判断文件是否存在
  43. * @param file
  44. * @return
  45. */
  46. public static boolean isExist(File file){
  47. if(null != file && file.exists()){
  48. return true;
  49. }
  50. return false;
  51. }
  52. }
  1. import java.io.File;
  2. import java.io.FileInputStream;
  3. import java.io.FileNotFoundException;
  4. import java.io.InputStream;
  5.  
  6. import org.apache.commons.lang3.StringUtils;
  7.  
  8. public class FileExecute {
  9.  
  10. public InputStream getFileInputStream(String filePath){
  11. if(StringUtils.isNotBlank(filePath)){
  12. File file = new File(filePath);
  13. if(FileUtil.isExist(file)){
  14. try {
  15. return new FileInputStream(file);
  16. } catch (FileNotFoundException e) {
  17. e.printStackTrace();
  18. return null;
  19. }
  20. }
  21. }
  22. return null;
  23. }
  24. }
  1. import java.io.File;
  2.  
  3. import org.junit.Assert;
  4. import org.junit.Test;
  5. import org.mockito.Mockito;
  6. import org.powermock.api.mockito.PowerMockito;
  7. import org.powermock.core.classloader.annotations.PrepareForTest;
  8.  
  9. import com.powerMockito.util.TestRunner;
  10.  
  11. @PrepareForTest({FileUtil.class})
  12. public class FileExecuteTest extends TestRunner{
  13. private FileExecute fileExecute = new FileExecute();
  14.  
  15. @Test
  16. public void testGetFileInputStream() {
  17. String filePath = PathUtil.getClassPath() + "FileExecute.properties";
  18. PowerMockito.mockStatic(FileUtil.class);
  19. PowerMockito.when(FileUtil.isExist(Mockito.any(File.class))).thenReturn(false);
  20. Assert.assertNull(fileExecute.getFileInputStream(filePath));
  21.  
  22. PowerMockito.verifyStatic(); //可以使用verifyStatic方法来校验静态Mock是否执行,该方法表示校验静态Mock是否执行一次
  23. }
  24. }

(2) 设置类中的静态共有final变量

在类(A类)中定义了公有静态final常量,类(B类)中会用到A类的静态常量,在测试B中该方法,可能希望改变这个静态常量的值来进行正常测试(如果测试方法使用静态常量原来值无法进行测试,但程序正常执行时用静态常量原来值是可以执行的且是正确的)。在测试方法中的做法是可以先生成A类对象,通过WhiteBox来更改该常量值。当然测试类上仍然需要有 @RunWith 及 @PrepareForTest

 三、静态类公共方法调用其自身私有方法

  1. import java.io.File;
  2. import java.io.FileInputStream;
  3. import java.io.FileNotFoundException;
  4. import java.io.InputStream;
  5.  
  6. import org.apache.commons.lang3.StringUtils;
  7.  
  8. /**
  9. * <p>静态类</p>
  10. * @version V1.0
  11. */
  12. public class StaticFileExecute {
  13. /***常量***/
  14. private static final String HELLO = new String("hello");
  15. /***非常量静态私有方法****/
  16. private static String NO_HELLO = "noHello";
  17.  
  18. private static InputStream getFileInputStream(String filePath){
  19. if(StringUtils.isNotBlank(filePath)){
  20. File file = new File(filePath);
  21. if(FileUtil.isExist(file)){
  22. try {
  23. return new FileInputStream(file);
  24. } catch (FileNotFoundException e) {
  25. e.printStackTrace();
  26. return null;
  27. }
  28. }
  29. }
  30. return null;
  31. }
  32.  
  33. public static String getStaticFinalHello(){
  34. return HELLO;
  35. }
  36.  
  37. public static String getFinalNoHello(){
  38. return NO_HELLO;
  39. }
  40.  
  41. public static boolean hasInputStream(String filePath){
  42. InputStream inputstream = getFileInputStream(filePath);
  43. if(null != inputstream){
  44. return true;
  45. }
  46. return false;
  47. }
  48. }
  1. mport static org.junit.Assert.*;
  2.  
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5.  
  6. import org.junit.Assert;
  7. import org.junit.Test;
  8. import org.junit.runner.RunWith;
  9. import org.mockito.Mockito;
  10. import org.powermock.api.mockito.PowerMockito;
  11. import org.powermock.core.classloader.annotations.PrepareForTest;
  12. import org.powermock.modules.junit4.PowerMockRunner;
  13.  
  14. /**
  15. * <p>针对静态类中的方法进行测试</p>
  16. * @version V1.0
  17. */
  18. @RunWith(PowerMockRunner.class)
  19. @PrepareForTest({FileUtil.class,StaticFileExecute.class})
  20. public class StaticFileExecuteTest {
  21. private String filePath = PathUtil.getClassPath() + "FileExecute.properties";
  22.  
  23. /**
  24. * 公共静态方法调用私有静态方法,对私有静态方法进行mock
  25. * @throws Exception
  26. */
  27. @Test
  28. public void testHasInputStream() throws Exception {
  29. PowerMockito.spy(StaticFileExecute.class);
  30. PowerMockito.doReturn(null).when(StaticFileExecute.class,"getFileInputStream",filePath);
  31. Assert.assertFalse(StaticFileExecute.hasInputStream(filePath));
  32. /***静态方法被执行了一次***/
  33. PowerMockito.verifyPrivate(StaticFileExecute.class,Mockito.times()).invoke("getFileInputStream",filePath);
  34.  
  35. PowerMockito.doReturn(new FileInputStream(new File(filePath))).when(StaticFileExecute.class,"getFileInputStream",filePath);
  36. Assert.assertTrue(StaticFileExecute.hasInputStream(filePath));
  37. /***静态方法被执行了二次***/
  38. PowerMockito.verifyPrivate(StaticFileExecute.class,Mockito.times()).invoke("getFileInputStream",filePath);
  39. }
  40.  
  41. @Test
  42. public void testGetStringsAfterSplit() {
  43. fail("Not yet implemented");
  44. }
  45.  
  46. }

在示例中,静态类 StaticFileExecute 中的 公共静态 hasInputStream 方法使用私有方法 getFileInputStream。对 hasInputStream 进行测试的时候,需要将 getFileInputStream 方法 mock 掉。mock步骤:

  • 对 StaticFileExecute 静态类型进行spy mock;(spy mock 出的表示对象除非指明when,才会返回指定的内容,否则真实执行);
  • 对静态类中的私有方法进行mock;(使用doReturn,这样程序不会进入私有方法内部);
  • 校验私有方法被执行的次数,使用 verifyPrivate;

上述测试用例在Junit4的环境下可以成功执行,但是在统计覆盖率的时候,@preparefortest 中的类 覆盖率为0;为了能够统计出覆盖率,需要进行修正。

(1)  eclipse 使用 插件;

  • 使用 EclEmma Java Code Coverage for Eclipse 插件;
  • 修改测试类中内容,使用JavaAgent 及 rule;
  1. import static org.junit.Assert.fail;
  2.  
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5.  
  6. import org.junit.Assert;
  7. import org.junit.Ignore;
  8. import org.junit.Rule;
  9. import org.junit.Test;
  10. import org.mockito.Mockito;
  11. import org.powermock.api.mockito.PowerMockito;
  12. import org.powermock.core.classloader.annotations.PrepareForTest;
  13. import org.powermock.modules.agent.PowerMockAgent;
  14. import org.powermock.modules.junit4.rule.PowerMockRule;
  15.  
  16. /**
  17. * <p>针对静态类中的方法进行测试</p>
  18. * @version V1.0
  19. */
  20. @PrepareForTest({FileUtil.class,StaticFileExecute.class})
  21. public class JavaAgentStaticExecuteTest {
  22. private String filePath = PathUtil.getClassPath() + "FileExecute.properties";
  23. @Rule
  24. public PowerMockRule rule = new PowerMockRule();
  25. static {
  26. PowerMockAgent.initializeIfNeeded();
  27. }
  28. /**
  29. * 公共静态方法调用私有静态方法,对私有静态方法进行mock
  30. * @throws Exception
  31. */
  32. @Test
  33. public void testHasInputStream() throws Exception {
  34. PowerMockito.spy(StaticFileExecute.class);
  35. PowerMockito.doReturn(null).when(StaticFileExecute.class,"getFileInputStream",filePath);
  36. Assert.assertFalse(StaticFileExecute.hasInputStream(filePath));
  37. /***静态方法被执行了一次***/
  38. PowerMockito.verifyPrivate(StaticFileExecute.class,Mockito.times()).invoke("getFileInputStream",filePath);
  39.  
  40. PowerMockito.doReturn(new FileInputStream(new File(filePath))).when(StaticFileExecute.class,"getFileInputStream",filePath);
  41. Assert.assertTrue(StaticFileExecute.hasInputStream(filePath));
  42. /***静态方法被执行了一次***/
  43. PowerMockito.verifyPrivate(StaticFileExecute.class,Mockito.times()).invoke("getFileInputStream",filePath);
  44. }
  45.  
  46. @Ignore
  47. public void testGetStringsAfterSplit() {
  48. fail("Not yet implemented");
  49. }
  50.  
  51. }
  • 在执行的时候,需要配置JVM参数: -ea -noverify -javaagent:D:/XXXX/.m2/repository/org/powermock/powermock-module-javaagent/1.7.0/powermock-module-javaagent-1.7.0.jar

POM 文件配置:

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.</modelVersion>
  4. <groupId>com.powerMockito.example</groupId>
  5. <artifactId>PowerMockitoExample</artifactId>
  6. <version>0.0.-SNAPSHOT</version>
  7.  
  8. <properties>
  9. <junit.version>4.12</junit.version>
  10. <mockito-all.version>1.10.</mockito-all.version>
  11. <powermock.version>1.7.</powermock.version>
  12. <hamcrest-library.version>1.3</hamcrest-library.version>
  13. <commons-collections.version>3.2.</commons-collections.version>
  14. <commons-lang3.version>3.1</commons-lang3.version>
  15. <commons-io.version>1.4</commons-io.version>
  16. <slf4j-log4j12.version>1.6.</slf4j-log4j12.version>
  17. </properties>
  18. <dependencies>
  19. <dependency>
  20. <groupId>junit</groupId>
  21. <artifactId>junit</artifactId>
  22. <version>${junit.version}</version>
  23. <scope>test</scope>
  24. </dependency>
  25.  
  26. <dependency>
  27. <groupId>org.slf4j</groupId>
  28. <artifactId>slf4j-log4j12</artifactId>
  29. <version>${slf4j-log4j12.version}</version>
  30. </dependency>
  31.  
  32. <!-- powermock -->
  33. <dependency>
  34. <groupId>org.mockito</groupId>
  35. <artifactId>mockito-all</artifactId>
  36. <version>${mockito-all.version}</version>
  37. <scope>test</scope>
  38. </dependency>
  39. <dependency>
  40. <groupId>org.powermock</groupId>
  41. <artifactId>powermock-module-junit4</artifactId>
  42. <version>${powermock.version}</version>
  43. <scope>test</scope>
  44. </dependency>
  45. <dependency>
  46. <groupId>org.powermock</groupId>
  47. <artifactId>powermock-api-mockito</artifactId>
  48. <version>${powermock.version}</version>
  49. <scope>test</scope>
  50. </dependency>
  51. <dependency>
  52. <groupId>org.powermock</groupId>
  53. <artifactId>powermock-module-junit4-rule-agent</artifactId>
  54. <version>1.7.</version>
  55. <scope>test</scope>
  56. </dependency>
  57. <dependency>
  58. <groupId>org.powermock</groupId>
  59. <artifactId>powermock-classloading-xstream</artifactId>
  60. <version>1.7.</version>
  61. <scope>test</scope>
  62. </dependency>
  63. <dependency>
  64. <groupId>org.hamcrest</groupId>
  65. <artifactId>hamcrest-library</artifactId>
  66. <version>${hamcrest-library.version}</version>
  67. <scope>test</scope>
  68. </dependency>
  69. <dependency>
  70. <groupId>commons-collections</groupId>
  71. <artifactId>commons-collections</artifactId>
  72. <version>${commons-collections.version}</version>
  73. </dependency>
  74. <dependency>
  75. <groupId>org.apache.commons</groupId>
  76. <artifactId>commons-lang3</artifactId>
  77. <version>${commons-lang3.version}</version>
  78. </dependency>
  79. <dependency>
  80. <groupId>commons-io</groupId>
  81. <artifactId>commons-io</artifactId>
  82. <version>${commons-io.version}</version>
  83. </dependency>
  84. </dependencies>
  85. <build>
  86. <plugins>
  87. <plugin>
  88. <groupId>org.apache.maven.plugins</groupId>
  89. <artifactId>maven-compiler-plugin</artifactId>
  90. <configuration>
  91. <source>1.8</source>
  92. <target>1.8</target>
  93. </configuration>
  94. </plugin>
  95. <!-- findbugs -->
  96. <plugin>
  97. <groupId>org.codehaus.mojo</groupId>
  98. <artifactId>findbugs-maven-plugin</artifactId>
  99. <configuration>
  100. <threshold>High</threshold>
  101. <effort>Default</effort>
  102. <findbugsXmlOutput>true</findbugsXmlOutput>
  103. <findbugsXmlOutputDirectory>target/site/findbugs</findbugsXmlOutputDirectory>
  104. </configuration>
  105. </plugin>
  106. <plugin>
  107. <groupId>org.apache.maven.plugins</groupId>
  108. <artifactId>maven-surefire-plugin</artifactId>
  109. <version>2.20</version>
  110. <configuration>
  111. <argLine>-Xms256m -Xmx256m -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m -Dfile.encoding=utf- -javaagent:${settings.localRepository}\org\powermock\powermock-module-javaagent\1.7.\powermock-module-javaagent-1.7..jar -ea -noverify</argLine>
  112. <useSystemClassloader>true</useSystemClassloader>
  113. <includes>
  114. <include>**/*Test.java</include>
  115. </includes>
  116. </configuration>
  117. </plugin>
  118. <!-- cobertura -->
  119. <plugin>
  120. <groupId>org.codehaus.mojo</groupId>
  121. <artifactId>cobertura-maven-plugin</artifactId>
  122. <configuration>
  123. <format>xml</format>
  124. <encoding>utf-8</encoding>
  125. <instrumentation>
  126. <includes>
  127. <include>**/*.class</include>
  128. </includes>
  129. </instrumentation>
  130. </configuration>
  131. </plugin>
  132. </plugins>
  133. </build>
  134. </project>

(2) Maven跑单元测试

如果通过 Maven 命令跑通单元测试,并生成测试报告与覆盖率报告。需要如上图的 POM文件的配置。但需注意的是:目前执行命令 clean package  cobertura:cobertura  直接统计覆盖率会报错,还没有找到解决方案。

补充说明

使用该工具进行Mock的时候,需要注意PowerMock有两个重要的注解:

–@RunWith(PowerMockRunner.class)

–@PrepareForTest( { YourClassWithEgStaticMethod.class })

如果单元测试用例里没有使用注解@PrepareForTest,那么可以不用加注解@RunWith(PowerMockRunner.class),反之亦然。当需要使用PowerMock强大功能(Mock静态、final、私有方法等)的时候,就需要加注解@PrepareForTest。

(1)     某个实例对象或静态类部分方法需要mock,其它方法正常执行

该种情况主要发生在一个单元测试用例中,在该测试用例中,设计的逻辑是对某个实例对象或静态类的一个方法进行mock,使其返回自己想要的结果,而去别的方法在该用例中正常执行。此时可以使用PowerMockito.spy()。示例如下:

@Before

public void before() throws Exception{

observable = PowerMockito.spy(InstallProgressObservable.getDefaultInstance());   //spy的对象类要放入到@prepareForTest中

PowerMockito.doNothing().when(observable, "notifyObs");

observable.setDetail("");

}

说明:

在上面的代码中mock了InstallProgressObservable对象,而只有执行该对象的notifyObs方法时,才不执行任何动作。其它方法均真实执行。spy的对象类要放入到@prepareForTest中。这里把模拟结果(PowerMockito.doNothing)放在when前面,表示不会真是执行后面的方法,否则程序中会真是执行到,则不会达到模拟的效果。

(2)     Mock静态类的公有静态方法

对静态类的静态方法进行mock,指定其返回模拟数据,此时可以使用PowerMockito.mockStatic方法,并使用PowerMockito.verifyStatic进行校验,主要是校验静态方法是否被执行到。

示例如下:

@Test

public void testStartTool() throws Exception {

PowerMockito.mockStatic(CmdUtil.class);

PowerMockito.doReturn(false).when(CmdUtil.class,"cmdBool",Mockito.anyString(),   Mockito.anyString(), Mockito.anyVararg());   //这种写法仅在mock的对象填写仅@PrepareForTest中才可以

Whitebox.invokeMethod(ToolInstall.class, "startTool", toolInfo,observable);

PowerMockito.verifyStatic(Mockito.times(1));

CmdUtil.cmdBool(Mockito.anyString(), Mockito.anyString(), Mockito.anyVararg());

}

说明:

在上面的代码中mock了CmdUtil.cmdBool方法,首先使用PowerMockito.mockStatic模拟静态类(该静态类需要登记到 @PrepareForTest中);其次是进行对该静态类中的某个方法进行mock数据;最后在执行完成之后,进行静态类的校验,判断mock的静态方法是否被执行,使用PowerMockito.verifyStatic注意:在这行后面需要将mock的静态方法再执行一遍。

(3)     执行私有方法

在写单元测试用例的时候,可以直接针对私有方法写单元测试用例,此时面临调用私有方法的情况,通常情况下,我们会写反射类来执行我们测试的私有方法,但是当需要校验参数,让参数为null的时候,直接使用反射类是不行的,需要在反射类的基础上做些额外的逻辑。面对该问题,PowerMockito提供了调用私有方法的方式,直接使用Whitebox.invokeMethod。

示例如下:

@Test

public void testStartTool() throws Exception {

Whitebox.invokeMethod(ToolInstall.class, "startTool", toolInfo,observable);

}

说明:

在上面的代码中直接使用Whitebox.invokeMethod即可,如果是要对私有方法进行null参数校验,参数要指明是什么类型,如上面的代码改为:Whitebox.invokeMethod(ToolInstall.class,

"startTool", (ToolInfo)null,(InstallProgressObservable)null);

(4)     Mock静态类私有方法

桌面程序中经常出现直接调用静态类的方法,而该方法又会调用该类的其它私有静态方法。写单元测试时,有时需要将静态私有方法进行mock,模拟各种数据校验测试的静态方法的逻辑性,此时就需要对静态私有方法进行Mock,也就是该类的一部分方法要正常执行,另一部分要被mock掉。面对该中情况下,使用PowerMockito.spy,校验私有方法的执行情况,使用PowerMockito.verifyPrivate。

示例如下:

@Test

public void testInstallTool_product_notool() throws Exception   {

PowerMockito.spy(ToolInstall.class);    PowerMockito.doReturn(null).when(ToolInstall.class,"getInstallableTool",productName,rootInstallPath);

ToolInstall.installTool(productName,   rootInstallPath, observable);

PowerMockito.verifyPrivate(ToolInstall.class, Mockito.times(1)).invoke("getInstallableTool", productName,rootInstallPath);

PowerMockito.doReturn(Collections.emptyMap()).when(ToolInstall.class,"getInstallableTool",productName,rootInstallPath);

ToolInstall.installTool(productName,  rootInstallPath, observable);

PowerMockito.verifyPrivate(ToolInstall.class, Mockito.times(2)).invoke("getInstallableTool", productName,rootInstallPath);

}

说明:

在上面的代码中Mock了ToolInstall 静态类中的getInstallableTool 静态私有方法,而该类的公有installTool静态方法调用getInstallableTool私有方法,测试代码的意图是想让该私有方法返回mock的数据。直接使用PowerMockito.spy mock静态类(该ToolInstall静态类需要登记到 @PrepareForTest中),使用PowerMockito.doReturn….when…..的方式mock私有方法,校验时使用PowerMockito.verifyPrivate,第一个参数为静态类,第二个参数为执行次数。在使用PowerMockito.verifyPrivate时,必须在其返回对象直接使用invoke方法,否则该校验不起作用;invoke中要指明mock的私有方法名称及私有方法需要的参数,该参数应该与mock该方法时使用的一致。

(5)     Mock构造函数

在一个测试方法中若需对被测方法中的某个对象生成进行模拟,此时需要对其构造函数进行mock,直接生成测试方法中指定的对象。可以使用PowerMockito.whenNew。

示例如下:

@Test

public void testGetInstallableTool_no_tool_directory() throws Exception{

File toolFile = new File("D:\\hello");

PowerMockito.whenNew(File.class).withArguments(Mockito.anyString()).thenReturn(toolFile);

Map<String,ToolInfo> toolInfoMap = (Map<String,   ToolInfo>)TestReflectUtil.callPrivateMethod(ToolInstall.class, "getInstallableTool", this.productName,this.rootInstallPath);

Assert.assertTrue(CollectionUtil.isEmpty(toolInfoMap));

}

说明:

在上面的代码中对ToolInstall静态类的getInstallableTool方法进行了测试,getInstallableTool方法中要生成File对象,此用例对生成的File对象进行Mock(该ToolInstall静态类需要登记到 @PrepareForTest中),指向指定的文件夹。代码中使用了PowerMockito.whenNew(File.class).withArguments(Mockito.anyString()).thenReturn(toolFile); 这句进行了mock,模拟返回的对象为测试方法中创建的File对象。

(6)     阻止静态代码块执行

某个静态类中有静态代码块。由于每次执行一个Test类,都会重新加载该静态类,每加载一次静态类,静态代码块均会被执行。有时不希望执行静态代码,此时可以在测试类中使用注解 @SuppressStaticInitializationFor。

示例如下:

@SuppressStaticInitializationFor("com.hikvision.discinstall.language.core.TranslatorFactory") //阻止静态代码块运行

public class TranslatorFactoryTest{

@Rule

public PowerMockRule rule = new PowerMockRule();

static {

PowerMockAgent.initializeIfNeeded();

}

}

说明:

如果多个静态类都在该测试类中被执行到,且这些类都有静态代码块,该注解中的值使用数组的形式。使用该方式有一点不好的地方就是登记到该注解的静态类类,其中的被赋予初始值的静态属性均不生效,值均为null。为了让静态属性赋值仍然生效,此时需要使用PowerMockRule和Agent。要引入powermock-module-junit4-rule-agent.jar包,且测试类中不能使用@RunWith(PowerMockRunner.class),具体可见上述代码中test类中的代码,此时必须有该段代码,但有该段又引入另一个问题,此时无法进行bug调试,打断点不生效,因此建议在调试测试用例时,可以不先禁止静态代码块的执行,当没有问题时,再禁止即可。

(7)     覆盖率统计

被测试类在测试方法中被mock掉,且登记到了@PrepareForTest注解中时,此时进行代码统计,被测试类不会被统计到。此时需要使用PowerMockRule。具体用法见(6)中的代码说明部分。

(8)     Mock jdk提供的静态方法

当被测试方法中调用了jdk的静态方法,且想在测试方法中将其mock掉,除了安装mock静态类的公有方法方式来之外,还需要将调用jdk静态方法所属类登记到测试类中的@PrepareTest中。

示例如下:

@PrepareForTest({LanguageUtil.class,Locale.class})

public class LanguageUtilTest{

@Rule

public PowerMockRule rule = new   PowerMockRule();

static {

PowerMockAgent.initializeIfNeeded();

}

@Test

public void testGetSystemLanguage_fail() throws Exception {

//系统提供的静态方法,需要将调用静态方法的类放入到prepareForTest

PowerMockito.mockStatic(Locale.class);

PowerMockito.doReturn(null).when(Locale.class,"getDefault");

Assert.assertTrue(StringUtils.isBlank(LanguageUtil.getSystemLanguage()));

}

@Test

public void testUUID() throws Exception{

PowerMockito.mockStatic(UUID.class);

PowerMockito.doReturn(null).when(UUID.class,"randomUUID");

Assert.assertFalse(LanguageUtil.testUUID());

}

}

说明:

在该实例中要测试LanguageUtil.getSystemLanguage()方法,该方法在实现时调用了jdk的Locale.getDefault()方法,此时要对它进行Mock,使用PowerMockito.mockStatic方式,同时需要将Local类及LanguageUtil类登记到@ PrepareForTest中。

(9)     对常量进行设置

在写单元测试用例时,也经常会对某个静态类中的某个常量进行模拟值,此时可以使用Whitebox.setInternalState。

示例如下:

@PrepareForTest({PathConstants.class})

public class ConfigResolverNoPrepareTest extends   TestRunner{

@Test

public void   generateViewConfig_main() throws Exception{

Whitebox.setInternalState(PathConstants.class, "PRODUCT_PARENT_PATH",PathConstants.CLASS_PATH + "platform");    //私有静态

}

说明:

使用Whitebox.setInternalState可以对任意的对象属性或类属性进行设置模拟值。但是需要注意的是,若是对常量设置值,需要将类登记到测试类的@PrepareForTest中。

非web下的PowerMockito单元测试的更多相关文章

  1. XAMPP环境访问非Web DocumentRoot下绝对路径

    假设你的XAMPP网站文档根目录在C:/xampp/apache/htdocs/下面,那么访问这个目录下的文件是很直接的. 但是有时候需要把用户上传文件指定到特殊目录,比如E盘,那么就需要用户能够访问 ...

  2. 【.net 深呼吸】自定义缓存配置(非Web项目)

    在前一篇烂文中,老周简单讲述了非Web应用的缓存技术的基本用法.其实嘛,使用系统默认方案已经满足我们的需求了,不过,如果你真想自己来配置缓存,也是可以的. 缓存的自定义配置可以有两种方案,一种是用代码 ...

  3. 【.net深呼吸】非 Web 项目使用缓存

    从.net 4 开始,非web项目也可以使用缓存技术,故曰:.net 4 乃框架成熟之标志也. 对于缓存嘛,耍过 ASP.NET 的伙伴们肯定知道,这么说吧,就是将一些使用频率较高的数据放于内存中,并 ...

  4. Spring在非web应用中关闭IoC容器 (registerShutdownHook)

    在基于web的ApplicationContext实现中,已有相应的实现来处理关闭web应用时恰当地关闭Spring IoC容器.但,如果你正在一个非web应用的环境下使用Spring的IoC容器,如 ...

  5. 一步一步学习SignalR进行实时通信_9_托管在非Web应用程序

    原文:一步一步学习SignalR进行实时通信_9_托管在非Web应用程序 一步一步学习SignalR进行实时通信\_9_托管在非Web应用程序 一步一步学习SignalR进行实时通信_9_托管在非We ...

  6. springmvc 项目完整示例02 项目创建-eclipse创建动态web项目 配置文件 junit单元测试

    包结构 所需要的jar包直接拷贝到lib目录下 然后选定 build path 之后开始写项目代码 配置文件 ApplicationContext.xml <?xml version=" ...

  7. C#获取Web和非Web程序的目录

    几种方法如下:非Web程序 1.AppDomain.CurrentDomain.BaseDirectory 2.Environment.CurrentDirectory 3.HttpRuntime.B ...

  8. C#里面获取web和非web项目路径

    非Web程序获取路径几种方法如下: 1.AppDomain.CurrentDomain.BaseDirectory  2.Environment.CurrentDirectory 3.HttpRunt ...

  9. 非web工程,打jar放shell执行

    作为6年经验的程序员,一直在搞web服务应用开发,今天领导被吐槽了,只会web方面的东东,最基本的打包啥啥都不会.. 一般开发工程都是web项目,突然要求开发非web,不用tomcat装(浪费端口号) ...

随机推荐

  1. mac下mysql的卸载和安装

    1. mysql的卸载 1 sudo rm /usr/local/mysql 2 sudo rm -rf /usr/local/mysql* 3 sudo rm -rf /Library/Startu ...

  2. Java并发框架:Executor

    介绍 随着当今处理器中可用的核心数量的增加, 随着对实现更高吞吐量的需求的不断增长,多线程 API 变得非常流行. Java 提供了自己的多线程框架,称为 Executor 框架. 1. Execut ...

  3. JAVA 从一个List里删除包含另一个List的数据

    /** * 从listA里删除listB里有的数据 * @param listA * @param listB * @return */ public static List<String> ...

  4. 为什么Java只有值传递?

    形参和实参 形式参数,是在方法定义阶段,是定义某个函数时使用的参数,用于接收实参传入.例f(x,y)中x和y是形参. 实际参数,是在方法调用阶段,是主调函数调用有参函数时,实际传递的内容.例f(3,7 ...

  5. RedisDesktopManager远程连接Linux系统的Redis服务

    linux下安装redis :https://www.runoob.com/redis/redis-install.html 进入 src 运行redis   : ./redis-server 打开另 ...

  6. 网络设置管理 NetSetMan Pro v4.7.1 Lite 绿色便携版

    下载地址:点我 基本介绍 Netsetman是一个小巧好用的工具,你可以设置六组不同的网络参数值,针对不同的网络环境,而调用不同的参数,当你在家中.学校.工作单位等不同环境切换网络配置文件时,只需要通 ...

  7. SpringCloud解析之Ribbon

    Ribbon是分布式微服务架构中负载均衡的一个解决方案,我们只需要引入ribbon依赖,然后初始化一个RestTemplate对象,在其上添加@LoadBalanced注解,就可以实现请求的负载均衡, ...

  8. 两个域名同时访问一个tomcat下的两个项目

    两个域名,分别映射一个TOMCAT底下,两个应用. 分三个步骤完成. 1.域名与IP的解析,此步骤在万网等机构完成. 2.APACHE的httpd.conf的配置 <VirtualHost *: ...

  9. CDQZ集训DAY8 日记

    又一次翻车…… 先提一句昨晚的事.昨天晚上身后一帮成都七中的人用十分戏谑的语气交出了达哥的名字,看着NOI2017的获奖名单,如果他们真的是在嘲笑的话,真的挺想上去干他们一顿的…… 上午考试第一题一脸 ...

  10. binlog_format日志错误

    客户磁盘空间不够用,发现mysql的err日志文件已每天大概600M-800M的速度增长,开头考虑作日志切割,打开发现,整个7.8G的文件里面百分之99的文件全部是如下所示的warning警告信息 1 ...