差異處

這裏顯示兩個版本的差異處。

連向這個比對檢視

java:junit:powermock:diffexpectresult [2013/02/25 13:38]
127.0.0.1 外部編輯
java:junit:powermock:diffexpectresult [2023/06/25 09:48]
行 1: 行 1:
-{{tag>>​java powermock}} 
-====== 不同的Expected Result ====== 
-===== Problem ===== 
-為了讓程式夠強健,在發生能夠處理的例外情況可能會做retry。在[[http://​teddy-chen-tw.blogspot.tw/​2010/​03/​5-spare-handler.html|搞笑談軟工]]有提到retry好的做法,也可以透過spring的[[http://​static.springsource.org/​spring-batch/​apidocs/​org/​springframework/​batch/​retry/​support/​RetryTemplate.html|RetryTemplate]]去實做retry(很大包..)。\\ 
-但在測試的時候,要怎麼確認你的retry是否可以work呢?​ 讓我們來看看範例。這個範例在執行時,如果有例外產生的時候,會使用替代方案執行,如果超過重試次數就會拋出一個RuntimeException。 
-<code java> 
-package org.tonylin.powermock;​ 
  
-public class RetryExample { 
- public User readUser(){ 
- int attempt = 0; 
- int maxAttempt = 2; 
- boolean retry = false; 
- User user = null; 
- do { 
- try { 
- retry = false; 
- if (attempt == 0) 
- user = DaoUtil.readUserFromDB();​ 
- else 
- user = DaoUtil.readUserFromFile();​ 
- } catch (Exception e) { 
- attempt++;​ 
- retry = true; 
- if (attempt > maxAttempt) 
- throw new RuntimeException(e);​ 
- } 
- } while (attempt <= maxAttempt && retry); 
- return user; 
- } 
-} 
-</​code>​ 
-測試案例可以這樣設計:​\\ 
-  * 第一次執行成功。 
-  * 第一次失敗,改由readUserFromFile執行成功。 
-  * 第一次執行失敗,第二次執行readUserFromFile失敗,第三次才成功。 
-  * 執行皆失敗。 
-該如何透過PowerMock去實做這些測試案例呢?​ 
-===== How to resolve? ===== 
-**第一次執行成功**這個案例較基本,我就不特別說明。 
-==== 宣告 ==== 
-首先我們要先宣告PowerMock相關的annotation:​ 
-<code java> 
-@RunWith(PowerMockRunner.class) 
-@PrepareForTest({RetryExample.class,​ DaoUtil.class}) 
-public class TestRetryExample { 
- 
-} 
-</​code>​ 
-==== 第一次失敗,改由readUserFromFile執行成功 ==== 
-這個案例不難實做,首先讓readUserFromDB拋exception,readUserFromFile回傳User物件。需要驗證的內容,包含取得的物件必須與我們建立的mock物件吻合,還要確認程式先執行readUserFromDB再執行readUserFromFile。因此我在mock DaoUtil時,使用了**mockStaticStrict**,這會讓PowerMock.verifyAll()驗證流程必須依照我們所宣告的順序。 
-<code java> 
-@Test 
-public void testReadUser_failureAtFirstTime(){ 
- User mockUser = PowerMock.createMock(User.class);​ 
- PowerMock.mockStaticStrict(DaoUtil.class);​ 
- 
- DaoUtil.readUserFromDB();​ 
- PowerMock.expectLastCall().andThrow(new RuntimeException()).once();​ 
-  
- DaoUtil.readUserFromFile();​ 
- PowerMock.expectLastCall().andReturn(mockUser).once();​ 
-  
- PowerMock.replayAll();​ 
-  
- RetryExample retryExample = new RetryExample();​ 
- User user = retryExample.readUser();​ 
- assertEquals(mockUser,​ user); 
- PowerMock.verifyAll();​ 
-} 
-</​code>​ 
-==== 執行皆失敗 ==== 
-即所有的請求都拋exception。在驗證的部分要去catch exception,如果沒發生exception就代表有問題。 
-<code java> 
-@Test 
-public void testReadUser_failure3Times(){ 
- PowerMock.mockStaticStrict(DaoUtil.class);​ 
- 
- DaoUtil.readUserFromDB();​ 
- PowerMock.expectLastCall().andThrow(new RuntimeException()).once();​ 
-  
- DaoUtil.readUserFromFile();​ 
- PowerMock.expectLastCall().andThrow(new RuntimeException()).times(2);​ 
-  
- PowerMock.replayAll();​ 
-  
- RetryExample retryExample = new RetryExample();​ 
-  
- try { 
- retryExample.readUser();​ 
- fail(); 
- } catch( Exception e ){ 
- PowerMock.verifyAll();​  
- } 
-} 
-</​code>​ 
-==== 第一次執行失敗,第二次執行readUserFromFile失敗,第三次才成功 ==== 
-這才是這篇的重點。為了能模擬同一個method會有不同的執行結果,我使用了PowerMock.expectLastCall().andAnswer()並且override answer()。接著透過一個flag去記錄是第幾次執行以決定要回傳的結果。 
-<code java> 
-@Test 
-public void testReadUser_failure2Times(){ 
- final User mockUser = PowerMock.createMock(User.class);​ 
- PowerMock.mockStaticStrict(DaoUtil.class);​ 
- 
- DaoUtil.readUserFromDB();​ 
- PowerMock.expectLastCall().andThrow(new RuntimeException()).once();​ 
-  
- DaoUtil.readUserFromFile();​ 
- PowerMock.expectLastCall().andAnswer(new IAnswer<​User>​() { 
- private int mTimes = 0; 
- @Override 
- public User answer() throws Throwable { 
- mTimes++;​ 
- if( mTimes == 1 ){ 
- throw new RuntimeException();​ 
- } 
- return mockUser; 
- } 
- }).times(2);​ 
-  
- PowerMock.replayAll();​ 
-  
- RetryExample retryExample = new RetryExample();​ 
- User user = retryExample.readUser();​ 
- assertEquals(mockUser,​ user); 
- PowerMock.verifyAll();​ 
-} 
-</​code>​ 
- 
-IAnswer其實還能取得輸入參數,好去回傳不同的結果,這部分等之後有機會再分享給大家。 
-=====    ===== 
----- 
-\\ 
-~~DISQUS~~