2013-07-02 15 views
6

Ho provato a utilizzare Mockito per simulare un pool di database (solo per il recupero dei dati), ma durante l'esecuzione di un test delle prestazioni che recuperava molte connessioni di simulazione in un periodo di tempo, la memoria era esaurita.Mockito lancia un OutOfMemoryError su un semplice test

Ecco un codice autonomo semplificato, che genera un OutOfMemoryError dopo circa 150.000 iterazioni di loop sulla mia macchina (nonostante ciò non sembra essere salvato globalmente, e tutto dovrebbe essere garbage collectable). Che cosa sto facendo di sbagliato?

import static org.mockito.Mockito.when; 

import java.sql.Connection; 

import org.mockito.Mock; 
import org.mockito.MockitoAnnotations; 

public class Test1 { 

    static class DbPool { 
     public Connection getConnection() {return null;} 
    } 

    @Mock 
    private DbPool dbPool; 

    @Mock 
    private Connection connection; 

    public Test1() { 
     MockitoAnnotations.initMocks(this); 
     when(dbPool.getConnection()).thenReturn(connection); 

     for(int i=0;i<1000000;i++) { 
      dbPool.getConnection(); 
      System.out.println(i); 
     } 
    } 

    public static void main(String s[]) {  
     new Test1(); 
    } 
} 
+0

Il più alto il mio utilizzo della memoria ottiene mai è ~ 950 MB (come misurato da [ 'Runtime. totalMemory'] (http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#totalMemory())). – Jeffrey

+0

Ma perché dovrebbe usare del tutto la memoria, in primo luogo? Non vengono creati riferimenti globali agli oggetti creati, eppure quando si esegue GC non viene raccolto nulla. – Tim

+0

Mockito sta facendo le cose dietro le quinte con le sue classi derise. Presumo che è dove viene utilizzata la maggior parte della memoria. – Jeffrey

risposta

12

Il problema è che l'oggetto simulato ricorda i dettagli di ogni chiamata, nel caso in cui si desideri verificarlo in seguito. Alla fine, inevitabilmente finirà la memoria. Quello che devi fare è occasionalmente resettare la simulazione, usando il metodo statico Mockito.reset, e stubare di nuovo il tuo metodo. Sfortunatamente, non c'è modo di cancellare le informazioni di verifica di un mock senza resettare anche lo stub.

Questo problema è coperto in dettaglio https://code.google.com/p/mockito/issues/detail?id=84

1

questo non genera un errore OutOfMemory per me così posso solo supporre è necessario aumentare la quantità di heapspace disponibile quando lo si esegue. Here's how you can do that.

+0

Ho aumentato lo spazio a 1 GB e, quando eseguo 10.000.000 anziché 1.000.000 di iterazioni, ricevo comunque un'OOM. Il problema è che sembra esserci una perdita di memoria da qualche parte in Mockito. – Tim

12

La risposta da David-Wallace spiega perché si esegue in un OOM: un oggetto fittizio è ricordare i dettagli di ogni chiamata.

Ma una domanda altrettanto importante è: ora cosa fare al riguardo? Oltre a quanto già suggerito David, le ultime versioni Mockito 1.10.19 così come imminente 2.0.x ora supportano le cosiddette stubOnly prende in giro (vedi javadoc):

stubOnly: un mock-stub solo fa non registra invocazioni di metodi, risparmiando così memoria ma impedendo la verifica delle invocazioni.

Scala esempio di utilizzo:

import org.mockito.Mockito 
val list = Mockito.mock(classOf[Foo], Mockito.withSettings().stubOnly()) 

// The syntax is a bit more concise when using ScalaTest's MockitoSugar 
val foo = mock[Foo](Mockito.withSettings().stubOnly()) 

esempio di utilizzo di Java (non testata):

import org.mockito.Mockito; 
Foo mock = Mockito.mock(Foo.class, Mockito.withSettings().stubOnly()); 
Problemi correlati