2009-11-03 7 views
9

In che modo un'unità verifica se è stato generato un nuovo thread per un'attività Runnable quando utilizza un ExecutorService?Come testare l'unità che ExecutorService genera un nuovo thread per l'attività?

Fondamentalmente, ho un pool di thread statici per la mia applicazione.

public static final ExecutorService executorService = Executors.newCachedThreadPool(); 

vorrei utilizzare questo pool di thread per i miei test di unità, piuttosto che beffardo uno fuori o iniettando un nuovo pool di thread, dal momento che diversi pool di thread possono alterare notevolmente il comportamento della mia applicazione (vs fisso memorizzato nella cache o programmato, ecc.); Voglio assicurarmi di testare il comportamento dell'applicazione con il suo pool di thread in fase di esecuzione.

Il pool di thread memorizzato nella cache sembra funzionare meglio per me. Il problema è che poiché è statico e i thread sono memorizzati nella cache per 60 secondi, solo il primo test genererà un nuovo thread nel pool, mentre i test successivi riutilizzeranno quel thread.

Unità codice di prova:

public void testDoCallExecutesTaskInAnotherThread() {  
    final Client client = this.createClient(); 
    final ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) client.getExecutorService(); // gets the static thread pool 
    final int initPoolSize = threadPoolExecutor.getPoolSize(); 
    final Response response = client.doCall(); 
    Assert.assertEquals(initPoolSize + 1, threadPoolExecutor.getPoolSize()); 
} 

I consigli per ottenere questo funzionamento, o un altro approccio del tutto sarebbe apprezzato.

+0

Perché ti importa se il client esegue la chiamata in un thread separato? Posso vedere preoccuparsi di cose del tipo, "quanto tempo ci vuole?" o "questa operazione risponde correttamente a un interrupt". Ma così com'è, questa sembra essere una scarsa applicazione di test unitari. – erickson

+0

Buona domanda. Questo particolare client deve eseguire una chiamata al servizio Web in modo asincrono in modo che non registri l'oggetto che la utilizza - un problema di prestazioni nella mia applicazione. Non sto aspettando una risposta, voglio solo assicurarmi che l'attività che effettua una chiamata al servizio web sia generata in modo asincrono. –

+0

Questo è quello che pensavo. Quindi quello che dovresti veramente verificare è se "trattiene l'oggetto che lo usa". Cioè, quanto ci vuole? Posso implementare doCall in modo tale che ci vogliono due giorni per tornare, ma comunque fa sì che l'executor crei un altro thread; il tuo test unitario sarebbe comunque passato, anche se il tuo criterio è stato violato. – erickson

risposta

19

Mock il ThreadFactory:

ThreadFactory mock = new CustomObservableThreadFactory(); 
    ExecutorService executorService = Executors.newCachedThreadPool(mock); 
  1. Iniettare l'ExecutorService nella classe in prova, come al solito
  2. ma utilizzare un ThreadFactory personalizzato per la creazione del ThreadPool cache: Il ThreadFactory sarà chiamato ogni volta un nuovo thread deve essere chiamato. È quindi possibile tracciare queste istanze come desiderato, ad es. Con un listener o contatore.