跳到主要內容

發表文章

目前顯示的是有「Mockito」標籤的文章

Mockito - Mockito with annotations

Introduction 為了減少大家重複撰寫mock、spy或captor等語法,Mockito提供了 annotation 去解決這個問題。此篇教學已經寫的非常淺顯易懂,我只針對它不足的部分做補充。 Enable Mockito Annotations 要使用這個功能之前,必須要去啟用它,最常使用的方式就是直接使用MockitoJUnitRunner當Runner: @RunWith ( MockitoJUnitRunner. class ) public class CheckConnectionCommandTest { // skip } 假如你已經使用了PowerMockRunner或SpringJUnit4ClassRunner當Runner,你就要從以下兩個方法選一個出來用。一個是在testcase setup去初始化: @Before public void init ( ) { MockitoAnnotations. initMocks ( this ) ; } 另外一個就是透過@Rule的方式: @Rule public MockitoRule initRule = MockitoJUnit. rule ( ) ; Reference Getting Started with Mockito @Mock, @Spy, @Captor and @InjectMocks

Code Coverage With PowerMock on static method

Problem PowerMock最強大的地方,就是可以幫我們mock static method,還可以幫我們mock private method、constructor,甚至Java System classes。開發新功能無法避免使用到舊有的程式碼,而舊有的程式碼勢必有使用static method的utility class。本篇文章將分享如何撰寫測試,讓你可以正常的看到SUT(software under test)程式碼的coverage。 How to? 以下是本篇文章範例的類別圖: SUT提供testMethod功能,會使用DOC(Depended-on Component)所提供的static method delegatedMethod。接下來我將使用PowerMockito去mock DOC static的行為: @RunWith ( PowerMockRunner. class ) @PrepareForTest ( { DOC. class } ) public class SUTTest { @Test public void shouldReturnMockData_WhenDelegateExecutionToStaticMockDOC ( ) { // Given String expectData = "MockData" ; mockStatic ( DOC. class ) ; doReturn ( expectData ) . when ( DOC. class ) ; DOC. delegatedMethod ( ) ;   // When SUT sut = new SUT ( ) ; String realData = sut. testMethod ( ) ;   // Then assertEquals ( expectData, realData ) ; } } 接下來我們使用JUnit+code coverage tool去跑測試,以下為執行結果: 由此可見,mock “一般”的static method並不會造成coverage問題。但為什麼會有人對coverage問題抱持疑問...

Mockito - Answer Contains Multiple Value

Problem 在撰寫retry行為的測試時,想必會遇到針對不同存取次數要回應不同的結果。本篇文章主要分享我所使用的方式。 (根據不同應用會有不同寫法,有新增我就會更新) How to? 依存取順序回應不同的值 import java.util.Arrays ; import java.util.LinkedList ; import java.util.Queue ;   import org.mockito.invocation.InvocationOnMock ; import org.mockito.stubbing.Answer ;   public class MultiValueAnswer < T > implements Answer < T > {   private Queue < T > answerValues = new LinkedList <> ( ) ;   @SafeVarargs public MultiValueAnswer ( T... values ) { answerValues. addAll ( Arrays . asList ( values ) ) ; }   public MultiValueAnswer ( ) { }   @Override public T answer ( InvocationOnMock invocation ) throws Throwable { return answerValues. remove ( ) ; }   public void addValue ( T value ) { answerValues. add ( value ) ; } } Reference Using Mockito with multiple calls to the same method with the same arguments

Mockito - Get Mock Class Type

Problem 在mock factory所產生出來的東西時,會希望寫成generic形式以reuse: private < T extends Command > CommandCreator mockCommandCreator ( T mockCommand ) { CommandCreator cmdCreator = mock ( CommandCreator. class ) ;   oReturn ( mockCommand ) . when ( cmdCreator ) ; cmdCreator. createCommand ( mockCommand. getClass ( ) ) ;   return cmdCreator ; } 然而,針對mockCommand去getClass通常會拿到以下結果: class org.tonylin.mockito.BatchCommand$$EnhancerByMockitoWithCGLIB$$6f5074eb 也因此無法達到mock效果。本篇文章分享解決這個問題的過程。 Lib Version 我們所使用的powermockito與mockito版本大致如下: (powermock項目比較多,省略部分) POWERMOCK_MOCKITO_VERSION = "1.6.6" POWERMOCK_API_MOCKITO_DEP = "org.powermock:powermock-api-mockito:$POWERMOCK_MOCKITO_VERSION" POWERMOCK_API_MOCKITO_COM_DEP = "org.powermock:powermock-api-mockito-common:$POWERMOCK_MOCKITO_VERSION" MOCKITO_VERSION = "1.10.19" MOCKITO_CORE_DEP = "org.mockito:mockito-core:$MOCKITO_VERSION" HAMCREST_VERSION = "1.3" HAMCREST_DEP = "org....

Mockito - Verify the calling order

Problem 測試除了驗證執行結果以外,有時我們也會需要驗證方法的呼叫順序。舉例來說,在多執行緒存取一個method時,我們透過lock機制去避免race condition問題,同時我們又希望機於fair lock去確保順序性,以下是我們的待測程式: public void method ( int value ) { try { lock. lock ( ) ; handler. handle ( value ) ; } finally { lock. unlock ( ) ; } } 因此,單元測試除了會確認最後結果外,也會希望確認呼叫順序是否如預期。 How to? 我們的測試程式會產生40個thread來存取代測程式。第一個thread會透過latch讓handler處於等待的狀態,值到其餘39個threads都已開始執行才會解鎖,而這些thread會依序寫入1~40。第一個thread等待可以模擬39個thread同時lock的情況。接著就是主角,Mockito的Inorder物件;使用它來達成我們測試存取順序的目的: InOrder order = Mockito. inOrder ( handler ) ; for ( int i = 1 ; i <= 40 ; i ++ ) { order. verify ( handler ) . handle ( i ) ; }

Powermockito - FAQ Mock constructor

Mock constructor public class Example { public Example ( ) { System . out . println ( "Default construsture" ) ; } public Example ( int a ) { System . out . println ( "Construsture: " + a ) ; } } @Test public void test ( ) throws Exception { Example example = PowerMockito. mock ( Example. class ) ;   PowerMockito. whenNew ( Example. class ) . withNoArguments ( ) . thenReturn ( example ) ; Example example1 = new Example ( ) ; assertEquals ( example, example1 ) ;   PowerMockito. whenNew ( Example. class ) . withAnyArguments ( ) . thenReturn ( example ) ; Example example2 = new Example ( 1 ) ; assertEquals ( example, example2 ) ;   PowerMockito. whenNew ( Example. class ) . withArguments ( Matchers. anyInt ( ) ) . thenReturn ( example ) ; Example example3 = new Example ( 1 ) ; assertEquals ( example, example3 ) ; } Partial Any public class Example { public Example ( ) {   } public void setData ...

Mock partial static method with PowerMockito

Problem 我們可以透過PowerMock的mockStaticPartial去mock部分的static method: PowerMock. mockStaticPartial ( System . class , "getProperty" ) ;   System . getProperty ( "test" ) ; PowerMock. expectLastCall ( ) . andReturn ( "test" ) . anyTimes ( ) ;   PowerMock. replayAll ( ) ;   System . out . println ( System . getProperty ( "test" ) ) ;   PowerMock. verifyAll ( ) ; 如果想用PowerMockito該如何做呢? 我們可以使用spy: How to? PowerMockito. spy ( System . class ) ; PowerMockito. doReturn ( "test" ) . when ( System . class , "getProperty" , "test" ) ;   // 如果是沒任何回傳值的method,可以使用PowerMockito.doNothing()   System . out . println ( System . getProperty ( "test" ) ) ; 這種寫法存在的問題有兩個, 如果要呼叫的method有overloading,且使用Matchers.any當參數,將導致NullPointerException。問題發生原因為PowerMock會將Matchers.any產生的類別型態,識別為null,在判斷呼叫參數時就發生問題。 如果method名稱有修改,將不容易查覺。 因此第二種寫法如下: PowerMockito. spy ( System . class ) ; PowerMockito. doReturn ( ...