2016-11-17 58 views
0

設置比方說,我有以下構造函數的類:如何嘲笑財產構造

public class MyImpl extends Abstract<Foo> { 

    @Autowired 
    private FooClass foo; 

    private final ThreadPoolExecutor executor; 

    public MyImpl(String name, int num) { 
     super(name); 
     this.executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(num); 

    } 

某處這個類有以下方法:

@Override 
    public void doThis() { 
     for (int i = 0; i < num; i++) { 
      executor.execute(() -> foo.doMethod()); 
     } 
     executor.shutdown(); 

     super.doThis(); 
    } 

現在,我想測試foo.doMethod已被調用4次executor.execute(any())executor.shutdown()也被調用了4次。

到目前爲止,我有

@RunWith(PowerMockRunner.class) 
@PrepareForTest(Executors.class) 
public class MyImplTest { 

    private static final int NUM = 4; 

    @Mock 
    private FooClass foo; 
    @Mock 
    private ThreadPoolExecutor executor; 
    @InjectMocks 
    private MyImpl imyImpl = new MyImpl("Name", NUM); 

    @Test 
    public void shouldCallFourTimes() throws Exception { 
     PowerMockito.mockStatic(Executors.class); 
     when(Executors.newFixedThreadPool(NUM)).thenReturn(foo); 

     myImpl.doThis(); 

     PowerMockito.verifyStatic(); 
     Executors.newFixedThreadPool(NUM); 
     verify(foo, times(NUM)).doMethod()); 

    } 

但是這是行不通的。 Mockito說,我的模擬執行器沒有任何交互。 由於@Autowired依賴不是構造函數的一部分,我需要使用@InjectMocks在該字段中指定構造函數。然而,到了I PowerMockito.mockStatic(Executors.class)時,MyImpl的構造函數已經通過「真實」Executors.newFixedThreadPool創建了自己的執行程序。

任何想法如何解決這個問題?

UPDATE: 顯然,這不是什麼大不了的改變設計,我現在有以下幾點:

public class MyImpl extends Abstract<Foo> { 

    @Autowired 
    private FooClass foo; 

    private final ThreadPoolExecutor executor; 

    public MyImpl(String name, ThreadPoolExecutor executor) { 
     super(name); 
     this.executor = executor; 
} 

測試:

@Mock 
private ThreadPoolExecutor executor; 
@InjectMocks 
private MyImpl imyImpl = new MyImpl("Name", executor); 

然而,executor是抵達時,不知何故空構造函數。

+0

你不應該用「新新對象MyImpl(「Name」,NUM)',@InjectMocks自動實例化一個 – kuhajeyan

+0

如果我不這樣做,Mockito會抱怨MyImpl沒有默認構造函數。請注意,'FooClass foo'不會作爲參數傳遞給構造函數 – user3083022

+0

關於如何將大大appreaciated – user3083022

回答

4

問題是MyImpl的設計。

而不是在構造函數中創建線程池執行器,它應該傳遞給它。您可以將當前構造函數的靜態工廠方法放在適當位置,以便您仍然可以使用現在使用的相同參數創建實例。

爲什麼你需要投到ThreadPoolExecutor?這可以讓你依賴於特定的實現。如果你不需要這個,你最好用java.util.concurrent.ExecutorService

然後,你有一切就位,使用普通的ExecutorService模仿普通mockito。

+0

是的我開始認爲這是唯一的方法 – user3083022

+0

我現在遇到了其他問題,雖然...我更新了問題 – user3083022

+1

@ user3083022不要在這種情況下使用@InjectMocks。直接在你的測試用例中創建實例。在構造函數被調用的時候,Mockito沒有機會評估'@ Mock'註釋。 – SpaceTrucker

0

我想問題會成爲你的模擬類沒有得到注入,

,你可以嘗試這樣的事情,

@Mock 
private FooClass foo; 
@Mock 
private ThreadPoolExecutor executor; 

private MyImpl imyImpl; 

@Before 
public void setUp() throws Exception { 
    imyImpl = new MyImpl("Name", NUM); 
    impl.setFoo(foo); 
    impl.setExecutor(executor); 
} 

//測試

+0

我不想允許從外部設置執行程序 – user3083022