2013-07-02 7 views
6

Próbowałem używać Mockito do symulacji puli bazy danych (tylko do pobierania danych), ale podczas uruchamiania testu wydajności, który pobrał wiele próbnych połączeń przez pewien czas, zabrakło pamięci.Mockito rzuca OutOfMemoryError na prostym teście

Oto uproszczony, niezależny kod, który wyrzuca OutOfMemoryError po około 150 000 powtórzeń pętli na moim komputerze (mimo że nic nie wydaje się być zapisane globalnie i wszystko powinno być dostępne do zbierania śmieci). Co ja robię źle?

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

Największą moją wykorzystanie pamięci zawsze dostaje to ~ 950 MB (mierzone [ 'Runtime. totalMemory'] (http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#totalMemory())). – Jeffrey

+0

Ale dlaczego w ogóle powinien wykorzystywać jakąkolwiek pamięć? Nie tworzone są żadne globalne odwołania do utworzonych obiektów, a jednak po uruchomieniu GC nic nie jest gromadzone. – Tim

+0

Mockito robi rzeczy za kulisami z wyśmiewanymi klasami. Zakładam, że w tym miejscu używana jest większość pamięci. – Jeffrey

Odpowiedz

12

Problem polega na tym, że fałszywy obiekt zapamiętuje szczegóły każdego inwokacji, na wypadek, gdyby później chciał to sprawdzić. W końcu nieuchronnie zabraknie mu pamięci. To co musisz zrobić, to od czasu do czasu resetować symulację, używając metody statycznej Mockito.reset i ponownie wywołać metodę. Niestety, nie ma sposobu, aby wyczyścić fałszywe informacje weryfikacyjne bez resetowania stubbingu.

Ten problem jest szczegółowo omówione w https://code.google.com/p/mockito/issues/detail?id=84

1

Nie spowodowało to błędu OutOfMemory, więc mogę tylko założyć, że musisz zwiększyć ilość dostępnej przestrzeni podczas jej uruchamiania. Here's how you can do that.

+0

Zwiększyłem ilość miejsca do 1 GB, a kiedy uruchomię 10 000 000 zamiast 1 000 000 iteracji, nadal otrzymuję OOM. Problem polega na tym, że wydaje się, że gdzieś w Mockito jest przeciek pamięci. – Tim

12

odpowiedzi przez david-Wallace wyjaśnia dlaczego napotkasz na OOM: a atrapa obiektu pamięta szczegóły każdego wywołania.

Ale równie ważnym pytaniem jest: co teraz z tym zrobić? Oprócz tego, co David już zasugerował, najnowsze wersje Mockito 1.10.19, a także zbliżający 2.0.x obsługują tzw stubOnly mocks (patrz javadoc):

stubOnly: a en-tylko pozornie nie nagrywa wywołania metod, dzięki czemu można zaoszczędzić pamięć, ale uniemożliwić weryfikację wywołań.

Scala przykład użycia:

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

przykład użycia Java (niesprawdzone):

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