2013-07-02 62 views
6

Tôi đã thử sử dụng Mockito để mô phỏng một nhóm cơ sở dữ liệu (để lấy dữ liệu), nhưng khi chạy một thử nghiệm hiệu suất đã truy xuất nhiều kết nối mô phỏng trong một khoảng thời gian, nó hết bộ nhớ. Dưới đây là một mã độc lập đơn giản, mà ném một OutOfMemoryError sau khoảng 150.000 vòng lặp lặp trên máy tính của tôi (mặc dù không có gì dường như được lưu trên toàn cầu, và tất cả mọi thứ nên được thu gom rác). Lưu ý: Tôi đang làm gì sai?Mockito ném ra một OutOfMemoryError trên một thử nghiệm đơn giản

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

Việc sử dụng bộ nhớ của tôi cao nhất từng được cho là ~ 950 MB (được đo bằng [ 'Runtime. totalMemory'] (http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#totalMemory())). – Jeffrey

+0

Nhưng tại sao nó nên sử dụng hết bộ nhớ ngay từ đầu? Không có tham chiếu toàn cục nào cho các đối tượng đã tạo được tạo ra, và khi bạn chạy GC không có gì được thu thập. – Tim

+0

Mockito đang làm những việc đằng sau hậu trường với các lớp được mô phỏng của nó. Tôi cho rằng đó là nơi hầu hết bộ nhớ đang được sử dụng. – Jeffrey

Trả lời

12

Vấn đề là đối tượng giả đang nhớ chi tiết về mọi yêu cầu, trong trường hợp bạn muốn xác minh nó sau này. Cuối cùng, nó chắc chắn sẽ hết bộ nhớ. Những gì bạn cần làm là thỉnh thoảng thiết lập lại mô hình, sử dụng phương pháp tĩnh Mockito.reset và lập lại phương thức của bạn. Thật không may, không có cách nào để xóa thông tin xác minh của một mô hình mà không cần phải đặt lại phần còn lại.

Vấn đề này được trình bày chi tiết tại https://code.google.com/p/mockito/issues/detail?id=84

1

Điều này không gây ra lỗi OutOfMemory cho tôi vì vậy tôi chỉ có thể giả sử bạn cần tăng số lượng vùng lưu trữ có sẵn khi bạn chạy. Here's how you can do that.

+0

Tôi tăng dung lượng lên 1GB và khi tôi chạy 10.000.000 thay vì 1.000.000 lần lặp, tôi vẫn nhận được OOM. Vấn đề là dường như có một rò rỉ bộ nhớ ở đâu đó trong Mockito. – Tim

12

Câu trả lời bởi david-wallace giải thích lý do tại sao bạn chạy vào một oom: một đối tượng giả được ghi nhớ chi tiết của mỗi sự thỉnh nguyện.

Nhưng một câu hỏi không kém phần quan trọng là: bây giờ phải làm gì với nó? Ngoài những gì David đã đề nghị, các phiên bản mới nhất Mockito 1.10.19 cũng như 2.0.x sắp tới bây giờ hỗ trợ cái gọi là stubOnly mocks (xem javadoc):

stubOnly: Một giả còn sơ khai chỉ không ghi phương thức invocations, do đó tiết kiệm bộ nhớ nhưng không cho phép xác minh các lời gọi.

Scala sử dụng ví dụ:

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

sử dụng Java ví dụ (chưa được kiểm tra):

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