簡單介紹如何使用PowerMock和Mockito來mock 1. 構造函數 2. 靜態函數 3. 枚舉實現的單例 4. 選擇參數值做為函數的返回值(轉)


本文將簡單介紹如何使用PowerMock和Mockito來mock
1. 構造函數
2. 靜態函數
3. 枚舉實現的單例
4. 選擇參數值做為函數的返回值
5. 在調用mock出來的方法中,改變方法參數的值

一點簡要說明:Mockito其實已經可以滿足大部分的需求,但是它的實現機制是使用cglib來動態創建接口的類的實例。但是這種實現方式不能用於構造函數和靜態函數,因為那需要使用類的字節碼(比如使用javassist). 所以我們才需要結合使用PowerMock.

1. mock構造函數, 如果有代碼沒有使用DI注入依賴實例,在單元測試中可以使用PowerMock來模擬創建對象。
注意的開始兩行的2個注解 @RunWith 和 @PrepareForTest
@RunWith比較簡單,后面始終是PowerMockRunner.class
@PrepareForText后面需要加的是調用構造函數的類名,而不是有構造函數的類本身。
在下面的例子中,我們要測試的類是:Helper, 在Helper類中調用了Somthing類的構造函數來創建實例。

@RunWith(PowerMockRunner.class)
@PrepareForTest(Helper.class)
public class HelperTest {
  @Mock
  private Something mockSomething;
      
  @InjectMocks
  private Helper helper;
      
  @Test
  public void doSomething() throws Exception {
      String argument = "arg";
          
      PowerMockito.whenNew(Something.class).withArguments(argument).thenReturn(mockSomething);//mock靜態字段時,也可以使用此方法
          
      // 調用需要測試方法
      helper.doSomething(argument);
          
      // 進行驗證
      verify(mockSomething).doIt();
  }
}


public class Helper {
  public void doSomething(String arg) {
      Something something = new Something(arg);
      something.doit();
  }
}


2,mock 靜態函數, 單例模式就是一個典型的會調用靜態函數的例子。 注意要點與mock構造函數相同。

class ClassWithStatics {
  public static String getString() {
    return "String";
  }

  public static int getInt() {
    return 1;
  }
}

@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassWithStatics.class)
public class StubJustOneStatic {
  @Test
  public void test() {
    PowerMockito.mockStatic(ClassWithStatics.class);

    when(ClassWithStatics.getString()).thenReturn("Hello!");

    System.out.println("String: " + ClassWithStatics.getString());
    System.out.println("Int: " + ClassWithStatics.getInt());
  }
}


3。mock枚舉實現的單例

SingletonObject.java 
public enum SingletonObject { 
    INSTANCE;
    private int num;
    protected void setNum(int num) {
        this.num = num;
    }
    public int getNum() {
        return num;
    }
}
SingletonConsumer.java

public class SingletonConsumer { 
    public String consumeSingletonObject() { 
        return String.valueOf(SingletonObject.INSTANCE.getNum());
    }
}
SingletonConsumerTest.java
@RunWith(PowerMockRunner.class) 
@PrepareForTest({SingletonObject.class})
public class SingletonConsumerTest {
    @Test public void testConsumeSingletonObject() throws Exception {
        SingletonObject mockInstance = mock(SingletonObject.class);
        Whitebox.setInternalState(SingletonObject.class, "INSTANCE", mockInstance);
        when(mockInstance.getNum()).thenReturn(42);
        assertEquals("42", new SingletonConsumer().consumeSingletonObject());
    }
}

4。返回參數值做為函數返回值。
mockito 1.9.5之后,提供一個方便的方法來實現這個需要,在這之前可以使用一個匿名函數來返回一個answer來實現。

when(myMock.myFunction(anyString())).then(returnsFirstArg());

其中returnsFirstArg()是org.mockito.AdditionalAnswers中的一個靜態方法。
在這個類中還有其他的一些類似方法
returnsSecondArg()

returnsLastArg()
ReturnsArgumentAt(int position)

 

5. 在調用mock出來的方法中,改變方法參數的值
when( myMock.someMethod( any( List.class ) ) ).thenAnswer( ( new Answer<Void>() {
    @Override
    public Void answer( InvocationOnMock invocation )
            throws Throwable {
        Object[] args = invocation.getArguments();
        List arg1 = (List)args[0];
        arg1.add("12345");
        return null;
    }
} ) );



Verifying with generic parameters
verify(someService).process(Matchers.<Collection<Person>>any());
verify(adunoMasterBaseProcessor).processBinFiles( anyListOf(File.class) );
http://www.blogjava.net/usherlight/archive/2015/06/16/425740.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM