2009-07-10 8 views
0

단위 테스트를 위해 DBUnit을 사용하는 최대 절전 모드 기반 응용 프로그램이 있습니다. 우리는 XML 테스트 데이터베이스를 가지고 있는데, 각 테스트의 setUp()에 dummy 데이터로로드되고 tearDown() 중에 삭제됩니다. 문제는 약 300 개의 테스트 후에 힙 메모리가 모두 소모되기 때문에 더 이상 IDE (이 경우 Intellij)에서 전체 제품군을 실행할 수 없다는 것입니다. JVM이 결국 포기하고 죽을 때까지 테스트는 ~ 0.3 초에서 30 초 이상 걸립니다.내 DBUnit 테스트가 왜 많은 메모리를 소비합니까?

개미의 junit 작업을 통해 테스트 슈트를 실행하면 아무런 문제가 없으며 개별 테스트를 실행하지도 않습니다. 그러나 CI 서버에서 빌드를 깨기보다는 코드베이스에 대한 대규모 리팩토링 변경 사항을 확인하기 전에 전체 제품군을 로컬에서 실행할 수 있어야합니다.

JVM에 대한 유일한 인수로 -Xmx512m을 사용하여 테스트를 실행합니다. 이는 CI 서버에서 작업을 실행할 때 ant에 전달하는 것과 동일한 양입니다.

package com.mycompany.test; 
// imports omitted for brevity 

public abstract class DBTestCase extends TestCase { 

    private final String XML_DATA_SET = "test/resources/mytestdata.xml"; 
    private Session _session; 
    private Configuration _config; 

    public DBTestCase(String name) { 
    super(name); 
    } 

    @Override 
    protected void setUp() throws Exception { 
    super.setUp(); 
    _config = new Configuration().configure(); 
    SessionFactory sf = _config.buildSessionFactory(); 
    // This is a singleton which is used the DAO's to acquire a session. 
    // The session must be manually set from the test's setup so that any 
    // calls to the singleton return this session factory, otherwise NPE 
    // will result, since the session factory is normally built during 
    // webapp initialization. 
    HibernateUtil.setSessionFactory(sf); 
    _session = sf.openSession(); 
    _session.beginTransaction(); 

    IDataSet dataSet = new FlatXmlDataSet(new File(XML_DATA_SET)); 
    DatabaseOperation.CLEAN_INSERT.execute(getConnection(), dataSet); 
    } 

    protected void tearDown() throws Exception { 
    super.tearDown(); 
    _session.close(); 
    } 

    protected IDatabaseConnection getConnection() throws Exception { 
    ConnectionProvider connProvider = ConnectionProviderFactory 
     .newConnectionProvider(_config.getProperties()); 
    Connection jdbcConnection = connProvider.getConnection(); 
    DatabaseConnection dbConnection = new DatabaseConnection(jdbcConnection); 
    DatabaseConfig dbConfig = dbConnection.getConfig(); 
    dbConfig.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new HsqldbDataTypeFactory()); 
    return dbConnection; 
    } 
} 

그것은 분명하다 : 이런 식으로 뭔가를 보이는, 우리는 테스트 클래스 모두에서 확장하는 클래스를 작성했습니다

<hibernate-configuration> 
    <session-factory> 
    <!-- Database connection settings --> 
    <property name="connection.driver_class">org.hsqldb.jdbcDriver</property> 
    <property name="connection.url">jdbc:hsqldb:mem:mydatabase</property> 
    <property name="connection.username">sa</property> 
    <property name="connection.password"/> 

    <!-- Other configuration properties --> 
    <property name="connection.pool_size">1</property> 
    <property name="jdbc.batch_size">20</property> 
    <property name="connection.autocommit">true</property> 
    <property name="dialect">org.hibernate.dialect.HSQLDialect</property> 
    <property name="current_session_context_class">thread</property> 
    <property name="cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property> 
    <property name="bytecode.use_reflection_optimizer">false</property> 
    <property name="show_sql">true</property> 
    <property name="hibernate.hbm2ddl.auto">create-drop</property> 

    <!-- Mappings (omitted for brevity) --> 
    <mapping resource="hbm/blah.hbm.xml"/> 
    </session-factory> 
</hibernate-configuration> 

: 내 최대 절전 모드 - test.cfg.xml은 다음과 같다 일부 메모리 누수가 여기에서 일어나고 있지만, 나는 어디 있는지 모른다. 어떻게 진단 할 수 있습니까?

답변

0

J-16 SDiZ의 답은 올바른 방향으로 작업하게 만들었지 만, 어떻게 해결할 수 있었는지에 대해 좀 더 자세한 정보를 제공 할 것이라고 생각했습니다. 문제의 근본 원인은 실제로 데이터베이스가 메모리에 계속 저장되어 있었지만 솔루션은 DBUnit의 DBTestCase 클래스에서 상속 받아 JUnit TestCase에서 상속하여 내 롤을 시도하지 않는 것이 었습니다. 내 테스트 케이스의 기본 클래스는 지금과 같이 보입니다 :이 클래스는 아주 잘 작동

public class MyTestCase extends DBTestCase { 
    private static Configuration _config = null; 

    public MyTestCase(String name) { 
    super(name); 
    if(_config == null) { 
     _config = new Configuration().configure(); 
     SessionFactory sf = _config.buildSessionFactory(); 
     HibernateUtil.setSessionFactory(sf); 
    } 

    System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, "org.hsqldb.jdbcDriver"); 
    System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, "jdbc:hsqldb:mem:mydbname"); 
    System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, "sa"); 
    System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, ""); 
    } 

    @Override 
    protected IDataSet getDataSet() throws Exception { 
    return new FlatXmlDataSet(new FileReader(MY_XML_DATA_FILE_NAME), false, true, false); 
    } 

    @Override 
    protected void setUpDatabaseConfig(DatabaseConfig config) { 
    config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new HsqldbDataTypeFactory()); 
    } 

을, 내 테스트 스위트 실행은 불과 30 초 몇 분에서 내려 갔다.

2

현재 메모리 데이터베이스를 사용하는 :

데이터베이스가 메모리에있는 모든 것을 의미
<property name="connection.driver_class">org.hsqldb.jdbcDriver</property> 
<property name="connection.url">jdbc:hsqldb:mem:mydatabase</property> 

. 캐시 된 테이블이있는 디스크 데이터베이스에서 사용하거나 각 테스트 후에 모든 것을 삭제하십시오.

관련 문제