2013-07-02 6 views
6

Ich habe versucht, mit Mockito einen Datenbankpool zu simulieren (nur zum Abrufen von Daten), aber bei einem Leistungstest, der viele Scheinverbindungen über einen bestimmten Zeitraum hinweg abgerufen hat, war der Speicher knapp.Mockito löst einen OutOfMemoryError bei einem einfachen Test aus

Hier ist ein vereinfachter, in sich abgeschlossener Code, der nach etwa 150.000 Schleifendurchläufen auf meinem Rechner einen OutOfMemoryError auslöst (obwohl nichts global gespeichert zu sein scheint und alles Müll-sammelbar sein sollte). Was mache ich falsch? Diese

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

Die höchste meine Speichernutzung je bekommt, ist ~ 950 MB (gemessen durch [ 'Runtime. totalMemory'] (http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#totalMemory())). – Jeffrey

+0

Aber warum sollte überhaupt überhaupt Speicher verwendet werden? Es werden keine globalen Verweise auf erstellte Objekte erstellt, und dennoch wird beim Ausführen von GC nichts gesammelt. – Tim

+0

Mockito macht Dinge hinter den Kulissen mit seinen verspotteten Klassen. Ich nehme an, dass dort der meiste Speicher verwendet wird. – Jeffrey

Antwort

12

Das Problem ist, dass das Mock-Objekt die Details jedes Aufrufs speichert, falls Sie es später überprüfen möchten. Irgendwann wird es unweigerlich aus dem Gedächtnis gehen. Was Sie tun müssen, ist gelegentlich den Schein zurückzusetzen, mit der statischen Methode , und stub Ihre Methode erneut. Leider gibt es keine Möglichkeit, die Verifizierungsinformation eines Scheines zu löschen, ohne auch den Stubbing zurückzusetzen.

Dieses Problem wird im Detail behandelt wird, bei https://code.google.com/p/mockito/issues/detail?id=84

1

hatte keine OutOfMemory Fehler werfen für mich, so kann ich nur annehmen, müssen Sie die Menge an heapspace zur Verfügung zu erhöhen, wenn Sie es starten. Here's how you can do that.

+0

Ich habe den Speicherplatz auf 1 GB erhöht, und wenn ich 10.000.000 statt 1.000.000 Iterationen verwende, bekomme ich immer noch ein OOM. Das Problem ist, dass es irgendwo in Mockito ein Speicherleck zu geben scheint. – Tim

12

Die Antwort von david-wallace erklärt, warum Sie in ein OOM laufen: ein Mock-Objekt Details von jedem Aufruf ist die Erinnerung.

Aber eine ebenso wichtige Frage ist: Was ist nun zu tun? Zusätzlich zu dem, was bereits vorgeschlagen David, unterstützen die neuesten Mockito Versionen 1.10.19 sowie kommender 2.0.x nun sogenannte stubOnly Mocks (siehe javadoc):

stubOnly: Ein Stub-only Mock nicht aufgezeichnet Methodenaufrufe, wodurch Speicher gespart wird, aber keine Überprüfung von Aufrufen möglich ist.

Scala Anwendungsbeispiel:

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()) 

Java Anwendungsbeispiel (nicht getestet):

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