Last active
January 12, 2022 04:28
-
-
Save fatmind/4110984 to your computer and use it in GitHub Desktop.
powermock example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package demo.powermock; | |
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; | |
import static org.junit.Assert.*; | |
@RunWith(PowerMockRunner.class) | |
@PrepareForTest(XxxService.class) //注意:非 XxxUtil.class | |
public class MockConstructionTest { | |
/* | |
* 1.Use the @RunWith(PowerMockRunner.class) annotation at the class-level of the test case. | |
* 2.Use the @PrepareForTest(ClassThatCreatesTheNewInstance.class) annotation at the class-level of the test case. | |
* 3.PowerMockito.whenNew(MockNewClass.class) | |
* 4.Note : withArguments(value), value必须与实际new时的参数类型相同 | |
*/ | |
@Test | |
public void mockConstruction() throws Exception { | |
//prepare | |
XxxService service = new XxxService(); | |
XxxUtil util = new XxxUtil(); | |
String name = "hello"; | |
util.setName(name); | |
PowerMockito.whenNew(XxxUtil.class).withNoArguments().thenReturn(util); | |
//action | |
XxxUtil res = service.getUtil(); | |
//assert | |
assertEquals(name, res.getName()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package demo.powermock; | |
/** | |
* 请大家自己测试 | |
* @author bohan.sj | |
*/ | |
public class MockFinalMethodOrClassTest { | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package demo.powermock; | |
import static org.mockito.Matchers.anyLong; | |
import static org.mockito.Mockito.*; | |
import java.io.File; | |
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(XxxUtil.class) // 注意:非 Thread.class | |
public class MockJavaCoreLibraryTest { | |
@Test | |
public void mockJavaCoreLibrary() throws Exception { | |
//prepare | |
PowerMockito.mockStatic(Thread.class); | |
//action | |
XxxUtil.sleep(1000); | |
//assert | |
PowerMockito.verifyStatic(times(1)); | |
Thread.sleep(anyLong()); | |
} | |
/** | |
* 关键点:withArguments(value), value必须与实际new时的参数相同 | |
* @throws Exception | |
*/ | |
@Test | |
public void readFile$mockNewFile() throws Exception { | |
//preapare | |
File file = mock(File.class); | |
PowerMockito.whenNew(File.class).withArguments(anyString()).thenReturn(file); | |
//action | |
XxxUtil.readFile(anyString()); | |
//assert | |
verify(file, times(1)).getAbsolutePath(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package demo.powermock; | |
import static org.junit.Assert.assertFalse; | |
import static org.mockito.Matchers.anyInt; | |
import static org.mockito.Mockito.times; | |
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; | |
// We prepare XxxServiceClass for test because it's final or we need to mock private or static methods | |
@RunWith(PowerMockRunner.class) | |
@PrepareForTest(XxxService.class) // spy是不需要声明 @PrepareForTest,但必须使用 doReturn("foo").when(spy).get(0); | |
public class MockPartialMethodTest { | |
private XxxService service = new XxxService(); | |
@Test | |
public void mockPartialPrivateMethod() throws Exception { | |
//prepare | |
service = PowerMockito.spy(service); | |
PowerMockito.doReturn(false).when(service, "isNeedHandle", anyInt()); // mock private method | |
/* | |
* spy must use doReturn() | |
* | |
List list = new LinkedList(); | |
List spy = spy(list); | |
//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) | |
when(spy.get(0)).thenReturn("foo"); | |
//You have to use doReturn() for stubbing | |
doReturn("foo").when(spy).get(0); | |
*/ | |
//action | |
boolean res = service.handle(2); | |
//assert | |
assertFalse(res); | |
PowerMockito.verifyPrivate(service, times(1)).invoke("isNeedHandle", anyInt()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package demo.powermock; | |
import static org.junit.Assert.assertFalse; | |
import static org.mockito.Matchers.anyInt; | |
import static org.mockito.Mockito.times; | |
import static org.mockito.Mockito.when; | |
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(XxxUtil.class) | |
public class MockStaticMethodTest { | |
@Test | |
public void mockStaticMethodAndVerifyStaticMethod() { | |
//prepare | |
XxxService service = new XxxService(); | |
PowerMockito.mockStatic(XxxUtil.class); | |
when(XxxUtil.isSafe(anyInt())).thenReturn(false); | |
//action | |
boolean res = service.isAllowBuy(2); | |
//assert | |
assertFalse(res); | |
/* | |
* 提示:静态方法verify有点别扭,如下是官方示例 | |
* | |
// Different from Mockito, always use PowerMockito.verifyStatic() first | |
PowerMockito.verifyStatic(Mockito.times(2)); | |
// Use EasyMock-like verification semantic per static method invocation | |
Static.firstStaticMethod(param); | |
// Remember to call verifyStatic() again | |
PowerMockito.verifyStatic(Mockito.never()); | |
Static.secondStaticMethod(); | |
*/ | |
PowerMockito.verifyStatic(times(1)); | |
XxxUtil.isSafe(anyInt()); | |
} | |
@Test(expected=RuntimeException.class) | |
public void mockStaticMethodThrowException() { | |
//prepare | |
XxxService service = new XxxService(); | |
PowerMockito.mockStatic(XxxUtil.class); | |
PowerMockito.doThrow(new RuntimeException()).when(XxxUtil.isSafe(anyInt())); | |
//action | |
service.isAllowBuy(2); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package demo.powermock; | |
import static org.junit.Assert.assertEquals; | |
import static org.junit.Assert.assertTrue; | |
import static org.mockito.Matchers.anyInt; | |
import static org.mockito.Mockito.times; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.Method; | |
import org.junit.Before; | |
import org.junit.Test; | |
import org.powermock.api.mockito.PowerMockito; | |
/** | |
* 注:当然可用反射实现同样目的,可认为powermock帮你提供工具类 | |
* @author bohan.sj | |
*/ | |
public class PrivateFieldOrMethodTest { | |
private XxxService target; | |
@Before | |
public void setUp() { | |
target = new XxxService(); | |
} | |
@Test | |
public void modifyPrivateField() throws Exception { | |
//prepare | |
Field f = PowerMockito.field(XxxService.class, "threshold"); | |
f.set(null, 10); | |
//action | |
int result = target.sum(); | |
//assert | |
assertEquals(10, result); | |
} | |
@Test | |
public void testPrivateMethod() throws Exception { | |
//preapre | |
Method m = PowerMockito.method(XxxService.class, "isPositiveNumber", new Class[]{int.class}); | |
//action | |
boolean res = (Boolean)m.invoke(target, 2); | |
//assert | |
assertTrue(res); | |
} | |
@Test | |
public void verifyPrivateMethodInvoke() throws Exception { | |
//prepare | |
//action | |
target.foreach(2); | |
//assert | |
PowerMockito.verifyPrivate(target, times(2)).invoke("isPositiveNumber", anyInt()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package demo.powermock; | |
public class XxxService { | |
/* | |
* 1.修改私有域 | |
* - unit test 必须保证 '快',需要修改private field | |
*/ | |
private static int threshold = 1000000; | |
public int sum() { | |
int i=0; | |
while(i < threshold) { | |
i=i+1; | |
} | |
return i; | |
} | |
/* | |
* 2.测试私有方法 | |
*/ | |
private boolean isPositiveNumber(int i) { | |
if(i > 0) { | |
return true; | |
} else { | |
return false; | |
} | |
} | |
/* | |
* 3.无返回值,校验:对某方法调用次数 | |
*/ | |
public void foreach(int count) { | |
for(int i=0; i<count; i++) { | |
isPositiveNumber(i); | |
} | |
} | |
/* | |
* 3.mock静态方法 | |
*/ | |
public boolean isAllowBuy(int i) { | |
//判断是否安全 | |
if(XxxUtil.isSafe(i)) { | |
//判断是否超过支付能力 | |
// .... | |
} | |
return false; | |
} | |
/* | |
* 4.mock partial method | |
* - 需要mock isNeedHandle(),否则导致单元测试粒度太大 | |
*/ | |
public boolean handle(int i) { | |
if(isNeedHandle(i)) { | |
// ... logic handle | |
return true; | |
} | |
return false; | |
} | |
private boolean isNeedHandle(int i) { | |
//假设此方法逻辑,依赖外部服务、且逻辑较复杂 | |
return true; | |
} | |
/* | |
* 5.mock construction | |
*/ | |
public XxxUtil getUtil() { | |
XxxUtil util = new XxxUtil(); | |
return util; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package demo.powermock; | |
import java.io.File; | |
public class XxxUtil { | |
public static boolean isSafe(int i) { | |
if(i > 0) { | |
return true; | |
} else { | |
return false; | |
} | |
} | |
private String name = "XxxUtil"; | |
public String getName() { | |
return name; | |
} | |
public void setName(String name) { | |
this.name = name; | |
} | |
/* | |
* 1. mock java core library | |
* - 无结果返回,只能verify方法是否被调用 | |
* - 且是Java自身类 | |
*/ | |
public static void sleep(long time) throws Exception { | |
Thread.sleep(time); | |
} | |
/* | |
* 2. mock java core library | |
* - new instance | |
*/ | |
public static void readFile(String filename) throws Exception { | |
File file = new File(filename); | |
System.out.println(file.getAbsolutePath()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The static method at MockJavaCoreLibraryTest.java L21 is not mocking any method. How can we mock a static method?