Comment tester avec DBUnit avec plaine JDBC et HSQLDB sans faire face à un NoSuchTableException?

StackOverflow https://stackoverflow.com/questions/1530951

Question

Je suis en train d'utiliser DBUnit avec JDBC simple et HSQLDB, et ne peut pas tout à fait le faire fonctionner - même si je l'ai utilisé DBUnit avec Hibernate plus tôt avec grand succès. Voici le code:

import java.sql.PreparedStatement;
import org.dbunit.IDatabaseTester;
import org.dbunit.JdbcDatabaseTester;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.XmlDataSet;
import org.junit.Test;

public class DummyTest {

    @Test
    public void testDBUnit() throws Exception {
        IDatabaseTester databaseTester = new JdbcDatabaseTester("org.hsqldb.jdbcDriver", "jdbc:hsqldb:mem", "sa", "");
        IDataSet dataSet = new XmlDataSet(getClass().getResourceAsStream("dataset.xml"));
        databaseTester.setDataSet(dataSet);
        databaseTester.onSetup();
        PreparedStatement pst = databaseTester.getConnection().getConnection().prepareStatement("select * from mytable");
    }
}

Et voici le dataset.xml en question:

<dataset>
    <table name="mytable">
        <column>itemnumber</column>
        <column>something</column>
        <column>other</column>
        <row>
            <value>1234abcd</value>
            <value>something1</value>
            <value>else1</value>
        </row>
    </table>
</dataset>

Ce test me donne un NoSuchTableException:

org.dbunit.dataset.NoSuchTableException: mytable
    at org.dbunit.database.DatabaseDataSet.getTableMetaData(DatabaseDataSet.java:282)
    at org.dbunit.operation.DeleteAllOperation.execute(DeleteAllOperation.java:109)
    at org.dbunit.operation.CompositeOperation.execute(CompositeOperation.java:79)
    at org.dbunit.AbstractDatabaseTester.executeOperation(AbstractDatabaseTester.java:190)
    at org.dbunit.AbstractDatabaseTester.onSetup(AbstractDatabaseTester.java:103)
    at DummyTest.testDBUnit(DummyTest.java:18)

Si je supprime la ligne, je reçois un SQLException databaseTester.onSetup () au lieu:

java.sql.SQLException: Table not found in statement [select * from mytable]
    at org.hsqldb.jdbc.Util.throwError(Unknown Source)
    at org.hsqldb.jdbc.jdbcPreparedStatement.<init>(Unknown Source)
    at org.hsqldb.jdbc.jdbcConnection.prepareStatement(Unknown Source)
    at DummyTest.testDBUnit(DummyTest.java:19)

L'ensemble de données en lui-même fonctionne, puisque je peux y accéder comme il se doit:

ITable table = dataSet.getTable("mytable");
String firstCol = table.getTableMetaData().getColumns()[0];
String tName = table.getTableMetaData().getTableName();

Qu'est-ce que je suis absent ici?

EDIT : Comme @mlk souligne, DBUnit ne crée pas les tables. Si j'insérer le texte suivant avant d'ajouter l'ensemble de données, tout se passe bien:

PreparedStatement pp = databaseTester.getConnection().getConnection().prepareStatement(
     "create table mytable ( itemnumber varchar(255) NOT NULL primary key, "
   + " something varchar(255), other varchar(255) )");
pp.executeUpdate();

Je posté une question de suivi comme Est-il possible pour DBUnit créer automatiquement des tables à partir d'un jeu de données ou dtd?

Était-ce utile?

La solution

DbUnit ne crée pas de tables. Elle ne pourrait pas les informations limitées données dans le fichier XML. Mise en veille prolongée, je crois peut créer les tables.

Ceci est l'une des raisons pour lesquelles je cessé d'utiliser des bases de données en mémoire et avons obtenu à la place le DBA pour donner à chaque développeur leur propre base de données. Chaque développeur conserve alors la base de données à jour en utilisant les mêmes scripts qui sont ensuite exécutées sur en direct. Cela ajoute une petite surcharge (tous les développeurs ont besoin de garder leurs bases de données à jour), mais signifie que vous n'avez pas besoin de déconner la construction de la base de données pour chaque course et vous pouvez être sûr que les requêtes ont couru dans le travail de test en direct.

La deuxième raison est la vitesse. J'ai trouvé dans la création de la base de données de la mémoire a pris beaucoup plus longtemps que simplement la connexion à une base de données existante.

La troisième raison est la déchirure vers le bas est pas destructif (démarrage essuie la base de données). Cela signifie que je peux exécuter le SQL testé sur la base de données pour aider à comprendre pourquoi un test est un échec.


Mise à jour : 20171115

Je l'ai depuis passé à l'aide règles JUnit qui commencent une véritable instance du serveur de base de données et quelque chose comme FlywayDB pour construire la base de données (et en utilisant les mêmes scripts en direct comme dans l'essai, l'application responsable de la construction de la base de données). Il est nettement plus lent que d'utiliser une base de données préconstruit. Cependant, l'utilisation microservices bien définis (et réduisant ainsi la fonctionnalité qui a besoin de tests) et d'être très serré qui teste obtient une base de données que vous pouvez faire migrer ces questions et obtenir les avantages de la base de données locale qui correspond toujours en direct.

Cela ne signifie hélas le test abattez est toujours destructrice, mais un point de rupture bien placé résout ce.

Autres conseils

... quelques années plus tard nous avons maintenant de meilleures options

Spring Boot / Spring JDBC peut initialiser une base de données avec JDBC simple.

  

Spring JDBC dispose d'une fonction d'initialisation DataSource. Spring Boot permet   par défaut et les charges SQL à partir des emplacements standards et schema.sql   data.sql (dans la racine du classpath). En outre Spring Boot   charger les fichiers schema-${platform}.sql et data-${platform}.sql (si   présent), où la plate-forme est la valeur de spring.datasource.platform,   par exemple. vous pouvez choisir de le définir au nom du fournisseur de la base de données   (Hsqldb, h2, oracle, mysql, postgresql etc.).

https: // docs .spring.io / ressort boot / documents / courant / référence / html / howto-base de données initialization.html

Dans le cas où vous créez vos tables dès le départ comme et toujours obtenir un NoSuchTableException, alors il y a quelque chose de mal avec le schéma . Avant de tourner maintenant fou, tripotant dans toutes sortes de façons étranges et merveilleuses, essayez de régler le paramètre de schéma PUBLIC lorsque vous créez le IDatabaseConnection, comme suit:

IDatabaseConnection databaseConnection = new HsqldbConnection(sqlConnection, "PUBLIC");

Il m'a fallu pas à pas dans le code DbUnit avec le débogueur, mais cela semble faire l'affaire.

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