Skip to content

Instantly share code, notes, and snippets.

@fatmind
Last active January 12, 2022 04:28
Show Gist options
  • Save fatmind/4110984 to your computer and use it in GitHub Desktop.
Save fatmind/4110984 to your computer and use it in GitHub Desktop.
powermock example
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());
}
}
package demo.powermock;
/**
* 请大家自己测试
* @author bohan.sj
*/
public class MockFinalMethodOrClassTest {
}
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();
}
}
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());
}
}
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);
}
}
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());
}
}
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;
}
}
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());
}
}
@sairam
Copy link

sairam commented Sep 1, 2015

The static method at MockJavaCoreLibraryTest.java L21 is not mocking any method. How can we mock a static method?

@yanzhilong
Copy link

gradle 要怎么依赖?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment