2016-12-07 128 views
4
public static ResponseBean call(Bean bean) throws Exception { 
    // statements... 
    IgnoreCall.ignoreMethodCall(bean); 
    // statements... 

    // return 
} 

通過上面的代碼段中,是有可能測試IgnoreCall.ignoreMethod(Bean)方法忽略調用而不需要將整個語句一個布爾條件下?忽略調用內部靜態呼叫

這裏的單元測試代碼片段:

@RunWith(PowerMockRunner.class) 
@PrepareTest 
public ClassHelperTest { 

    @Test 
    public void testCall() throws Excpetion { 
     // stubbing... 
     ResponseBean responseBean = ClassHelper.call(bean); 
     // verify/ies 
     // assert/s 
    } 

} 

注:

  • 重構ClassHelper.call(Bean)應該避免。即使採用糟糕的OO設計,重構成本也很高。
  • 方法簽名被鎖定,除非其他模式適用於替換。
  • 在目標靜態方法上使用Mockito.whenPowerMockito.when嘗試,在運行時調試時,stubbing不起作用。
+2

事情是:** static **是OO設計中的一個異常;正如你剛剛注意到的那樣:它使你的代碼更難以測試。 PowerMock可以「解決」這個問題;但我寧願推薦您更改您的生產代碼。沒有靜態調用,沒有這樣的問題。 – GhostCat

+0

如果重構很容易,那麼到那時我就完成了。不幸的是,由於手頭上的OO設計不佳,我陷入了困境。你提到'PowerMock可以解決這個問題',關心分享如何? –

+0

你會驚訝我多久會得到答案,建議修復破碎的設計,而不是使用PowerMock。無論如何,你現在得到了答案。 – GhostCat

回答

5

由於您的意見表明,更改您的生產代碼是不可能的,您只需「深入」PowerMock的靜態模擬方面;如例如所概述的here

基本上你需要啓用IgnoreCall進行靜態模擬;然後您撥打電話ignoreMethodCall() a no-op。

但是當你繼續問:核心問題,你的問題是要模擬出一個靜態方法是無效的事實。我在下面有一個完整的例子,但在此之前有一些解釋。

的一點是:你調用一個方法有兩個原因:

  1. 它有副作用
  2. 它返回一個值,也許,會導致副作用,也

A void方法可以只有被稱爲副作用。而事情是:當你做靜態嘲笑,那麼級別的作品。

含義:指示PowerMock「阻止」某些類的任何靜態方法執行;你只需「擦除」所有這些靜態方法的副作用!因此,通過告訴PowerMock進行這些靜態模擬,所有無效方法已經「消失」了。

但正如所說的,你也可以調用方法來獲得它們的返回值。然後是Mockito的when()方法開始。您使用該方法說:當該值返回方法被調用時,然後做這個或那個。

長話短說;這裏是一個使用你要的元素[MCVE]:

package ghostcat.test; 

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; 

class IgnoreCall { 
    public static void ignoreMethodCall(Object o) { 
    System.out.println("SHOULD NOT SHOW UP: " + o); 
    } 
} 

class CuT { 
    public static Object call(Object bean) { 
    System.out.println("statement1"); 
    IgnoreCall.ignoreMethodCall(bean); 
    System.out.println("statement2"); 
    return "whatever"; 
    } 
} 

@RunWith(PowerMockRunner.class) 
@PrepareForTest(IgnoreCall.class) 
public class PMTest { 
    @Test 
    public void test() { 
    PowerMockito.mockStatic(IgnoreCall.class); 
    CuT.call("yeha"); 
    } 
} 

如你的榜樣...有IgnoreCall;在那個我剛纔稱爲「call」的靜態方法中使用。

此打印:

statement1 
statement2 

當我進去註釋掉

//  PowerMockito.mockStatic(IgnoreCall.class); 

它打印:

statement1 
SHOULD NOT SHOW UP: yeha 
statement2 

所以,一個簡單的例子,應該告訴你正是你需要做什麼。

我使用eclipse neon和IBM java8 JDK,並將powermock-mockito-junit-1.6.6.zip中的所有JAR導入到我的測試項目中。

+0

無法理解爲什麼存根參數不起作用?使用'Mockito.when'和'PowerMockito.when',兩者都沒有相應的工作。 –

+0

這應該是被接受的答案。你讀過@GhostCat的鏈接嗎? 'PowerMockito.mockStatic(IgnoreCall.class);'並確保你正在使用PowerMocks跑步者。 –

+0

@CyrilHorad我也有點贊同大衛說的話。你看,你打算做的事情是*記錄在我連接的答案中。你在那裏失去了什麼?你真的需要人們爲你特別寫一個例子嗎? – GhostCat