我尝试使用Mockito来模拟数据库池(仅用于检索数据),但是当运行在一段时间内检索到许多模拟连接的性能测试时,内存不足。
这是一个简化的自包含代码,它在我的机器上进行大约150,000次循环迭代后抛出OutOfMemoryError(尽管似乎没有任何东西可以全局保存,并且所有内容都应该是垃圾可收集的)。我做错了什么?
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 :(得分:14)
david-wallace的回应解释了为什么遇到OOM:模拟对象正在记住每次调用的细节。
但一个同样重要的问题是:现在该怎么办呢?除了David已经提出的建议外,最新的Mockito版本1.10.19以及即将推出的2.0.x现在支持所谓的stubOnly
模拟(见javadoc):
stubOnly:仅存根模拟不记录方法调用,从而节省了内存但不允许验证调用。
Scala用法示例:
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使用示例(未经测试):
import org.mockito.Mockito;
Foo mock = Mockito.mock(Foo.class, Mockito.withSettings().stubOnly());
答案 1 :(得分:12)
问题是模拟对象正在记住每次调用的细节,以防您希望稍后进行验证。最终,它将不可避免地耗尽内存。您需要做的是偶尔使用Mockito.reset
静态方法重置模拟,并再次存根您的方法。不幸的是,如果没有重置存根,就无法清除模拟的验证信息。
答案 2 :(得分:1)
这并没有给我带来Out Of Memory错误,因此我只能假设您需要在运行时增加可用的堆空间量。 Here's how you can do that.