12
votes

TDD avec HSQLDB - Suppression des clés étrangères

J'utilise HSQLDB pour les tests d'intégration de la couche de données, ce qui est génial. Cependant, je constate que mes contraintes de clé étrangère entrent dans la voie de mes tests. Par exemple, pour tester une simple sélection sur une table, je dois insérer des données factices dans cinq tables supplémentaires. Cela me donne envie de jeter des choses.

J'ai des annotations JPA tout au long de notre code modèle et avez configuré Hibernate pour recréer le schéma (HBM2DDL.Create-Drop) dans la configuration. Les jointures sont interprétées correctement en tant que contraintes de clé étrangère lorsque les tables sont générées.

Qu'est-ce que je voudrais, c'est de:

  1. ne pas créer les clés étrangères initialement (idéales, la plus propre) ou
  2. Trouvez un moyen de supprimer programmatiquement toutes les clés étrangères de la base de données (un rendez-vous, mais aura le travail)

    Si c'est utile, j'utilise le printemps pour passer ces tests. Les tests en question hériter de abstraitTransAderaljunit4springContextTestStest .

    Que pensez-vous? Peut-il être fait?


0 commentaires

5 Réponses :


0
votes

J'envisagerais de passer du temps à créer quelques luminaires, éventuellement avec DBUnit, que vous insérez @Before.

BTW, AbstractTransActionAljunit4Test est obsolète au printemps 3.0


1 commentaires

Re: déprécié ... Je voulais dire "abstraittransactionaljunit4springcontextStest" que j'ai corrigé ci-dessus. FWIW Nous utilisons le printemps 2.5.



11
votes

Vous pouvez désactiver les contraintes FK avec les instructions suivantes: xxx

Vous pouvez l'exécuter via une instruction JDBC avant vos méthodes de test (et le remettez-le sur < code> vrai après).


3 commentaires

Merci!!! Vous avez juste coupé ma classe de test en deux. Fait intéressant, cela facilite également la racine où Hibernate provoque des jointures intérieures inutiles.


Pour toute personne utilisant l'abstraitTransActionaljunit4springContexTestSTS ... La magie est la suivante: SimpleJDBCtMPLEPLATE.GETJDBCOPERATIONS ()


@Roufamatic content que vous trouviez cela utile.



9
votes

J'ai rencontré le même problème lors de l'essai de tester mon DAO avec un jeu de données XML plat. Config est dbunit + hsqldb 2.2.8 + JUNIT4 + Spring + JPA-> Tous ensemble menant à

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"applicationContext-test.xml"})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, DataSetTestExecutionListener.class, ForeignKeyDisabling.class})


3 commentaires

C'est un moyen élégant de le faire.


Ne devriez-vous pas le revenir au début de chaque test (après la configuration de la DB) avec "Définir la base de données Intégrité référentielle vraie"?


L'établissement de ce code dans la configuration pourrait également répondre à vos besoins. Dans mon cas, toute la suite de tests dépendait de cette modification de la structure. Mais le résultat devrait être le même.



2
votes

le faire vite:

Définir référentialité_Integrity false; dans importer.sql fichier dans votre répertoire de ressources de test.

problème résolu rapidement et bien :)

Voici quelques informations sur importateur.sql http: // christopherlakey .Com / Articles / Import-SQL.HTML


0 commentaires

2
votes

base sur l'inspiration dans ce fil, j'ai créé une solution un peu plus robuste pour ce problème. Le point était que j'aime vraiment des contraintes lors de la course à l'exécution du test et de toutes les autres solutions qui le gardent handicapées. Ce code ne les désactivera que pour la durée de l'importation de donnéesT, puis les réactive. Et peut être facilement étendu pour supporter un autre moteur à dB:

import com.github.springtestdbunit.DbUnitTestExecutionListener;
import org.apache.log4j.Logger;
import org.dbunit.database.DatabaseDataSourceConnection;
import org.dbunit.database.IDatabaseConnection;
import org.springframework.test.context.TestContext;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * Class DisableForeignKeysDbUnitTestExecutionListener
 * Simple wrapper class around DbUnitTestExecutionListener, which - for the time of importing the database -
 * disables Foreign Key Constraints checks.
 * This class can be extended by simply overriding toggleForeignKeysConstraintsForDbEngine(Connection, String, boolean);
 * subclasses should always call super-implementation for default case.
 */
public class DisableForeignKeysDbUnitTestExecutionListener
    extends DbUnitTestExecutionListener
{
    private static final Logger logger = Logger.getLogger(DisableForeignKeysDbUnitTestExecutionListener.class);
    private Connection cachedDbConnection;

    @Override
    public void beforeTestMethod(TestContext testContext)
        throws Exception
    {
        this.toggleForeignKeysConstraints(testContext, false);
        super.beforeTestMethod(testContext);
        this.toggleForeignKeysConstraints(testContext, true);
    }

    /**
     * Method should perform query to disable foreign keys constraints or return false,
     * if it is not able to perform such query (e.g. unknown database engine)
     *
     * @param connection    Database connection
     * @param dbProductName Name of the database product (as reported by connection metadata)
     * @param enabled       Expected state of foreign keys after the call
     *
     * @return True, if there was suitable statement for specified engine, otherwise false
     *
     * @throws SQLException
     */
    protected boolean toggleForeignKeysConstraintsForDbEngine(Connection connection, String dbProductName, boolean enabled)
        throws SQLException
    {
        switch (dbProductName)
        {
            case "HSQL Database Engine":
                connection.prepareStatement("SET DATABASE REFERENTIAL INTEGRITY " + (enabled ? "TRUE" : "FALSE"))
                          .execute();
                return (true);
        }
        return (false);
    }

    private void toggleForeignKeysConstraints(TestContext testContext, boolean enabled)
    {
        try
        {
            Connection connection = this.getDatabaseConnection(testContext);
            String databaseProductName = connection.getMetaData().getDatabaseProductName();
            if (!this.toggleForeignKeysConstraintsForDbEngine(connection, databaseProductName, enabled))
            {
                throw new IllegalStateException("Unknown database engine '" + databaseProductName +
                                                    "'. Unable to toggle foreign keys constraints.");
            }
        }
        catch (Throwable throwable)
        {
            logger.error("Unable to toggle Foreign keys constraints: " + throwable.getLocalizedMessage());
        }
    }

    synchronized private Connection getDatabaseConnection(TestContext testContext)
        throws SQLException
    {
        if (this.cachedDbConnection == null)
        {
            DataSource dataSource = testContext.getApplicationContext().getBean(DataSource.class);
            if (dataSource == null)
            {
                throw new IllegalStateException("Unable to obtain DataSource from ApplicationContext. " +
                                                    "Foreign constraints will not be disabled.");
            }

            IDatabaseConnection dsConnection = new DatabaseDataSourceConnection(dataSource);
            this.cachedDbConnection = dsConnection.getConnection();
        }

        return (this.cachedDbConnection);
    }
}


0 commentaires