Skip to content

Instantly share code, notes, and snippets.

@zseashell
Forked from fatmind/MockConstructionTest.java
Created November 24, 2015 08:17
Show Gist options
  • Save zseashell/0d743f606863f46461e3 to your computer and use it in GitHub Desktop.
Save zseashell/0d743f606863f46461e3 to your computer and use it in GitHub Desktop.

Revisions

  1. @fatmind fatmind revised this gist May 4, 2014. 2 changed files with 2 additions and 2 deletions.
    3 changes: 2 additions & 1 deletion MockPartialMethodTest.java
    Original file line number Diff line number Diff line change
    @@ -10,8 +10,9 @@
    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) // 必须添加此声明,否则会导致mock时实际调用方法
    @PrepareForTest(XxxService.class) // spy是不需要声明 @PrepareForTest,但必须使用 doReturn("foo").when(spy).get(0);
    public class MockPartialMethodTest {

    private XxxService service = new XxxService();
    1 change: 0 additions & 1 deletion XxxUtil.java
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,3 @@

    package demo.powermock;

    import java.io.File;
  2. @fatmind fatmind revised this gist Jul 25, 2013. 2 changed files with 13 additions and 0 deletions.
    12 changes: 12 additions & 0 deletions MockPartialMethodTest.java
    Original file line number Diff line number Diff line change
    @@ -22,6 +22,18 @@ public void mockPartialPrivateMethod() throws Exception {
    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);

    1 change: 1 addition & 0 deletions XxxUtil.java
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@

    package demo.powermock;

    import java.io.File;
  3. @fatmind fatmind revised this gist Jun 24, 2013. 1 changed file with 13 additions and 7 deletions.
    20 changes: 13 additions & 7 deletions MockPartialMethodTest.java
    Original file line number Diff line number Diff line change
    @@ -1,26 +1,32 @@
    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;

    import static org.mockito.Matchers.*;
    import static org.mockito.Mockito.*;
    import static org.junit.Assert.*;

    @RunWith(PowerMockRunner.class)
    @PrepareForTest(XxxService.class) // 必须添加此声明,否则会导致mock时实际调用方法
    public class MockPartialMethodTest {

    @Test
    private XxxService service = new XxxService();

    @Test
    public void mockPartialPrivateMethod() throws Exception {
    //prepare
    XxxService service = new XxxService();
    service = PowerMockito.spy(service);
    PowerMockito.doReturn(false).when(service, "isNeedHandle", anyInt()); // mock private method

    //action
    boolean res = service.handle(2);

    //assert
    assertFalse(res);
    assertFalse(res);
    PowerMockito.verifyPrivate(service, times(1)).invoke("isNeedHandle", anyInt());
    }

  4. @fatmind fatmind revised this gist Nov 19, 2012. 7 changed files with 245 additions and 1 deletion.
    38 changes: 38 additions & 0 deletions MockConstructionTest.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,38 @@
    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());
    }

    }
    9 changes: 9 additions & 0 deletions MockFinalMethodOrClassTest.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,9 @@
    package demo.powermock;

    /**
    * 请大家自己测试
    * @author bohan.sj
    */
    public class MockFinalMethodOrClassTest {

    }
    48 changes: 48 additions & 0 deletions MockJavaCoreLibraryTest.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,48 @@
    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();
    }

    }
    27 changes: 27 additions & 0 deletions MockPartialMethodTest.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,27 @@
    package demo.powermock;

    import org.junit.Test;
    import org.powermock.api.mockito.PowerMockito;

    import static org.mockito.Matchers.*;
    import static org.mockito.Mockito.*;
    import static org.junit.Assert.*;

    public class MockPartialMethodTest {

    @Test
    public void mockPartialPrivateMethod() throws Exception {
    //prepare
    XxxService service = new XxxService();
    service = PowerMockito.spy(service);
    PowerMockito.doReturn(false).when(service, "isNeedHandle", anyInt()); // mock private method

    //action
    boolean res = service.handle(2);

    //assert
    assertFalse(res);
    PowerMockito.verifyPrivate(service, times(1)).invoke("isNeedHandle", anyInt());
    }

    }
    58 changes: 58 additions & 0 deletions MockStaticMethodTest.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,58 @@
    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);
    }

    }
    64 changes: 64 additions & 0 deletions PrivateFieldOrMethodTest.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,64 @@
    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());
    }

    }
    2 changes: 1 addition & 1 deletion XxxUtil.java
    Original file line number Diff line number Diff line change
    @@ -23,7 +23,7 @@ public void setName(String name) {

    /*
    * 1. mock java core library
    * - 无结果返回,只能verify方法是否被调用
    * - 无结果返回,只能verify方法是否被调用
    * - 且是Java自身类
    */
    public static void sleep(long time) throws Exception {
  5. @fatmind fatmind created this gist Nov 19, 2012.
    76 changes: 76 additions & 0 deletions XxxService.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,76 @@
    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;
    }

    }
    42 changes: 42 additions & 0 deletions XxxUtil.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,42 @@
    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());
    }

    }