2013-12-18 31 views
3

我試圖從java.util.concurrent包中模擬ExecutorService和Executors。無法在單獨的類中獲取Executor的模擬實例

如果我試圖讓對象在同一個類(測試類)中嘲笑對象,我能夠獲得模擬對象。但是,如果我嘗試在另一個類(我想測試的類)中獲取模擬對象,那麼它會從java.util.concurrent返回實際的對象。以下是代碼片段。

我想測試類:

public class MyClass 
{ 
    public void myMethod() 
    { 
     ExecutorService executorService = Executors.newFixedThreadPool(2, new MyThreadFactory()); 

     for (int count = 0; count < 2; count++) 
     { 
      executorService.submit(new Thread()); 
     } 
    } 
} 

class MyThreadFactory implements ThreadFactory 
{ 
    @Override 
    public Thread newThread(Runnable r) 
    { 
     return null; 
    } 
}  

我的測試類是什麼樣子:

@RunWith(PowerMockRunner.class) 
@PrepareForTest(Executors.class) 
public class MyClassTest 
{ 
    @Test 
    public void testMyMethod() 
    { 
     prepareMocks();    

     //Code to get mocked object (See testMethod below) 
    } 

    private void prepareMocks() 
    { 
     ExecutorService executorService = PowerMock.createMock(ExecutorService.class); 
     EasyMock.expect(executorService.submit(EasyMock.anyObject(Runnable.class))).andReturn(null).anyTimes(); 

     PowerMock.mockStatic(Executors.class); 
     EasyMock.expect(Executors.newFixedThreadPool(EasyMock.anyInt(), EasyMock.anyObject(ThreadFactory.class))).andReturn(executorService).anyTimes(); 

     PowerMock.replay(executorService, Executors.class); 
    } 
} 

如果MyClassTest.testMyMethod()是如下,它返回嘲笑oject。

@Test 
    public void testMyMethod() 
    { 
     prepareMocks(); 

     //Following code reurned mocked instance of ExecutorService 
     ExecutorService executorService = Executors.newFixedThreadPool(2, new MyThreadFactory()); 

     for (int count = 0; count < 2; count++) 
     { 
      executorService.submit(new Thread()); 
     } 
    } 

但是如果我更改測試方法來調用myClass.myMethod()返回實際的實例,而不是嘲笑例如在myMethod的()。

@Test 
public void testMyMethod() 
{ 
    prepareMocks(); 

    /* 
    * Within myClass.myMethod(), Executors.newFixedThreadPool() returns actual instance of ThreadPoolExecutor 
    * instead of mocked object 
    */ 
    MyClass myClass = new MyClass(); 
    myClass.myMethod(); 
} 

我期待在myClass.myMethod中獲得Executors/ExecutorService的模擬實例。

這是預期的行爲?任何人都可以解釋行爲嗎?我錯過了什麼?

回答

4

您需要讓班級知道將會有模擬傳入。在@PrepareForTest()中,請嘗試包括調用靜態的類。這樣你就可以告訴它模擬靜態的執行,並告訴它這個模擬將在哪裏發生。嘗試更新@PrepareForTest({Executors.class, MyClass.class})

當你有它,所以你的測試類直接調用靜態,你有Executors.class@PrepareForTest()所以它會知道「注入」模擬執行。當你調用你的其他類時,在運行時,你調用它的類不知道使用你的靜態類的模擬版本,這就是爲什麼它會使用它所知道的原始代碼,而不是它的範圍之外的模擬。添加調用靜態對象(您測試的對象)的類將允許您在運行時必須掛入的靜態模擬。

+0

你知道爲什麼它不總是必要的嗎?例如,當嘲笑會議。請考慮以下內容:http://ideone.com/LIl0H7(測試課程)和http://ideone.com/aPuEoL(外部課程)。 – Line