Question

J'ai une application mise en veille prolongée, qui utilise DBUnit pour les tests unitaires. Nous avons une base de données de test XML, qui se charge avec des données fictives dans le setUp () de chaque test et supprimé lors de la tearDown (). Le problème est que je ne peux plus courir toute la suite dans un IDE (dans ce cas, IntelliJ), car après environ 300 essais, la mémoire de tas obtient tous utilisés. Les tests vont de prendre ~ 0,3 secondes à plus de 30 secondes pour exécuter, jusqu'à ce que la machine virtuelle Java donne finalement et meurt.

Quand je lance la suite de tests via la tâche JUnit de fourmi, alors il n'y a aucun problème, ni en cours d'exécution est la suite de tests pour une classe individuelle. Cependant, j'aime être en mesure d'exécuter toute la suite au niveau local avant de vérifier dans les grands changements de refactoring à la base de code plutôt que de briser la construction sur le serveur CI.

Je courais la suite de tests avec -Xmx512m comme mon seul argument à la machine virtuelle Java, qui est le même montant que je passe à la fourmi lors de l'exécution de la tâche sur le serveur CI. Mon hibernate-test.cfg.xml ressemble à ceci:

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

Nous avons écrit une classe pour laquelle toutes les classes d'essai s'étendent à partir, ce qui ressemble à ceci:

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;
  }
}

Il est clair que certaines fuites de mémoire qui se passe ici, mais je ne sais pas où. Comment pourrais-je aller sur le diagnostic de cette?

Était-ce utile?

La solution 2

La réponse de J-16 SDiZ m'a travailler dans la bonne direction, mais je pensais que je fournirais un peu plus d'informations quant à la façon dont j'ai pu résoudre ce problème. La racine du problème est en effet que la base de données conservée étant stockées dans la mémoire, mais la solution devait hériter de la classe DBTestCase de DBUnit, essayez de ne pas rouler mon propre en héritant de la JUnit TestCase. Mon cas test de classe de base ressemble maintenant quelque chose comme ceci:

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

Cette classe fonctionne très bien, et mes courses de la suite de tests ont passé de quelques minutes à peine 30 secondes.

Autres conseils

Vous utilisez ici la base de données de la mémoire:

<property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="connection.url">jdbc:hsqldb:mem:mydatabase</property>

Cela signifie que tout dans la base de données est dans la mémoire. Soit utiliser sur la base de données de disque avec table en cache, ou assurez-vous tout laisser tomber après chaque test.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top