Comment faire un test avec DBUnit avec simple JDBC et HSQLDB sans faire face à une NoSuchTableException?

j'essaie D'utiliser DBUnit avec simple JDBC et HSQLDB, et je ne peux pas tout à fait le faire fonctionner -- même si J'ai utilisé DBUnit avec Hibernate plus tôt avec un 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 les données.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 le logiciel.la ligne onSetup (), j'obtiens une SQLException à la place:

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 rate ici?

EDIT : comme @mlk le souligne, DBUnit ne crée pas de tables. Si j'insère ce qui suit 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();

j'ai posté une question de suivi comme y a-t-il un moyen pour DBUnit de créer automatiquement tableaux tirés d'un ensemble de données ou d'une dtd?

16
demandé sur Community 2009-10-07 15:06:49

3 réponses

dbUnit ne crée pas de tables. Elle ne le pourrait pas non plus avec l'information limitée fournie dans le fichier XML. Hibernation je crois peut créer les tables.

C'est l'une des raisons pour lesquelles j'ai arrêté d'utiliser des bases de données en mémoire et j'ai demandé au DBA de donner à chaque développeur leur propre base de données. Chaque développeur garde alors la base de données à jour en utilisant les mêmes scripts qui sont ensuite lancés en direct. Cela ajoute un petit frais généraux (tous les développeurs ont besoin de garder leurs bases de données à jour) mais cela signifie que vous n'avez pas besoin de gâcher la construction de la base de données pour chaque exécution et vous pouvez être sûr que les requêtes ont couru dans le travail de test en direct.

La deuxième raison était la vitesse. J'ai trouvé que créer la base de données en mémoire prenait beaucoup plus de temps que de simplement se connecter à une base de données existante.

la troisième raison est que le démontage n'est pas destructeur (le démarrage efface la base de données). Cela signifie que je peux exécuter le SQL sous test sur la base de données pour aider à comprendre pourquoi un test est un échec.


mise à jour : 20171115

je suis depuis passé à l'aide règles JUnit qui démarrent une instance réelle 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 que dans test, avec l'application responsable de la construction de la base de données). Il est nettement plus lent que d'utiliser un prédéfini la base de données. Cependant, en utilisant des microservices bien définis (et donc réduire la fonctionnalité qui doit être testée) et étant très serré sur quels tests obtient une base de données, vous pouvez migrer de tels problèmes et obtenir les avantages de la base de données locale qui correspond toujours en direct.

cela signifie hélas que le démontage d'essai est toujours destructeur, mais un point de rupture bien placé résout cela.

19
répondu Michael Lloyd Lee mlk 2017-11-15 15:33:59

...plusieurs 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 fonctionnalité d'initialiseur de sources de données. Printemps de Démarrage permet il par défaut et charge SQL à partir des emplacements standard schema.sql et data.sql (à la racine du classpath). En outre Printemps Amorçage charger le Les fichiers schema-${platform}.sql et data-${platform}.sql (si présente), où plate-forme est la valeur de spring.datasource.platform , par exemple, vous pouvez choisir de définir le nom du fournisseur de la base de données (hsqldb,h2, oracle, mysql, postgresql etc.).

https://docs.spring.io/spring-boot/docs/current/reference/html/howto-database-initialization.html

4
répondu Asa 2017-08-01 21:21:56

dans le cas où vous créez vos tables à l'avance comme suggéré ici et obtenez toujours une NoSuchTableException, puis il ya quelque chose de mal avec le schéma. Avant que vous ne deveniez fou, tripotant avec elle dans toutes sortes de façons bizarres et merveilleuses, essayez de mettre le paramètre de schéma à PUBLIC quand vous créez le IDatabaseConnection , comme ceci:

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

il m'a fallu passer par le code DbUnit avec le débogueur mais ce qui semble faire l'affaire.

0
répondu raoulsson 2017-05-23 12:24:50