Notre application fonctionne dans la version 2.0.4. Après la mise à niveau vers 2.2.2.RELEASE, les tests d'intégration échouent. Je soupçonne qu'il y a une mauvaise configuration, et chaque test d'intégration ne nettoie tout simplement pas après lui-même ou il y a une initialisation supplémentaire qui n'était pas là avant. Je ne sais vraiment pas comment le réparer correctement.
Pour être précis. Chaque test fonctionne lorsqu'il est appelé séparément. Une fois exécutés, nous voyons des erreurs comme:
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "drop table somewhere.sometable if exists" via JDBC Statement
...
caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Cannot drop "SOME_TABLE" because "FKKJEJC7GUX6OTX5NGANQCMN83R, FK7WLRCFA21PY7CI3R4OL1OWODT, FKQPMY4YOVD3D6HBNT0XX92149P, FK1TG6AMM2NSM6UJTO9EJHPJIXY, FKLPTBKDKFCHE72RJ5RRRIH4ORJ" depends on it; SQL statement:
et
2019-12-16 21:11:00.075 org.Apache.Tomcat.util.modeler.Registry : The MBean registry cannot be disabled because it has already been initialised
ce qui me suggère que nous essayons de réinitialiser quelque chose déjà initialisé + il y a un mauvais ordre de gouttes dans l'initialisation hibernate. Mais je ne vois vraiment rien de mal de notre côté. Voyons quelques extraits:
annotations de test:
@RunWith(SpringRunner.class)
@ActiveProfiles(...)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SomeIT {
les tests sont exécutés via:
<plugin>
<groupId>org.Apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
<forkCount>0</forkCount>
<reuseForks>false</reuseForks>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
et application.properties pour les tests:
spring.jpa.database=H2
spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.hibernate.jdbc.batch_size=5
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true
spring.jpa.properties.hibernate.jdbc.batch_versioned_data=true
#this disables option to have opened tx in view IIUC. We don't rely on that, so this just removes warning logging from console.
spring.jpa.open-in-view=false
#used to select db initialization scripts.
spring.datasource.platform=org.hibernate.dialect.H2Dialect
spring.datasource.url=jdbc:h2:mem:somewhere;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;INIT=create schema if not exists somewhere
spring.datasource.driver-class-name = org.h2.Driver
#this is probably needed for @DataJpaTest: I have no idea how to configure @DataJpaTest so that it can run with
#autoconfigured H2 db, probably it's caused by having schema defined in entities. Anyways @DataJpaTest fails to
#create schema. So alternative is to configure one DB for whole app here, and this option forces all @DataJpaTest not to
#replace this configuration with autoconfigured db.
spring.test.database.replace=none
Modifications testées:
replace=none
, mais cela tue tous les tests unitaires (car le schéma n'est pas créé), et n'aide en rien les tests d'intégration.Solution actuelle: eh bien tout ce que j'ai pu trouver n'est pas de réutiliser db. Qui avec replace=none
n'est possible que via:
spring.datasource.url=jdbc:h2:mem:somewhere${random.uuid};DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;INIT=create schema if not exists somewhere
mais je déteste profondément cette "solution". Qu'est-ce qui peut provoquer une réinitialisation incorrecte de la base de données/des nettoyages manquants/ou quelle pourrait être la cause de tout cela?
(modifier: si vous connaissez mieux le titre de cette question, veuillez le suggérer. Merci).
J'ai eu le même problème et malheureusement réponse de Melkor n'a pas fonctionné pour nous car notre schéma était trop complexe pour écrire un script supprimant les tables dans un ordre correct.
H2 prend en charge suppression de tous les objets quelles que soient leurs dépendances, le script suivant peut donc réinitialiser l'ensemble de la base de données.
src/test/resources/drop-tables.sql
DROP ALL OBJECTS
Ensuite, spécifiez les propriétés de test pour utiliser le script pour supprimer des tables
src/test/resources/application.properties
spring.jpa.properties.javax.persistence.schema-generation.drop-source=script
spring.jpa.properties.javax.persistence.schema-generation.drop-script-source=drop-tables.sql
Je voulais vous faire savoir que j'ai trouvé une solution à ce problème. Avec javax.persistence
propriétés, vous pouvez définir un script de dépôt qui sera exécuté avant la création automatique du schéma.
Cela vous permet de spécifier l'ordre dans lequel les tables doivent être supprimées (dépendez d'abord des tables). Peut-être que jouer avec ceux-ci pourrait vous aider. Notez qu'ils remplacent le spring.jpa.hibernate.ddl
propriété.
spring.jpa.properties.javax.persistence.schema-generation.database.action=drop-and-create
spring.jpa.properties.javax.persistence.schema-generation.drop-source=script-then-metadata
spring.jpa.properties.javax.persistence.schema-generation.drop-script-source=drop-tables.sql