0

Je suis en train de faire face à quelques problèmes avec la création d'un environnement de test d'unité de base de données utilisant Arquillian. Mon projet fonctionne déjà dans un environnement Glassfish 3.1.2 basé sur Seam 3, JSF et MySQL. Cependant, lorsque vous tentez de configurer un environnement de test à l'aide d'Arquillian, les choses se gâtent.Arquillian, glassfish & h2database

Mon but ultime est un test unitaire basé sur Arquillian utilisant un serveur intégré de Glassfish et une base de données intégrée en mémoire h2. Je ne suis pas difficile en ce qui concerne le conteneur intégré, c'est juste que le guide JPA Arquillian a suggéré que le conteneur Weld minimal ne supporte pas JPA. C'est pourquoi j'ai opté pour Glassfish. Comme je ne suis pas encore proche de l'initialisation du contexte de persistance, je ne poste pas mon fichier persistence.xml.

Voici le POM j'ai fini avec ce jour:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 
    <groupId>ch.diction</groupId> 
    <artifactId>web-portal</artifactId> 
    <version>0.0.1-SNAPSHOT</version> 
    <name>Diction web portal</name> 
    <packaging>war</packaging> 

    <properties> 
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
     <jee.version>1.0.0.Final</jee.version> 
     <seam.version>3.1.0.Final</seam.version> 
     <primefaces.version>3.4</primefaces.version> 
     <primefaces.theme.version>1.0.8</primefaces.theme.version> 
     <drools.version>5.4.0.Final</drools.version> 
     <arquillian.version>1.0.2.Final</arquillian.version> 
     <arquillian.weld.version>1.0.0.CR3</arquillian.weld.version> 
     <junit.version>4.8.1</junit.version> 
     <h2.version>1.3.168</h2.version> 
     <weldcore.version>1.1.10-SNAPSHOT</weldcore.version> 
     <slf4j.version>1.6.6</slf4j.version> 
    </properties> 

    <build> 
     <sourceDirectory>src/main/java</sourceDirectory> 
     <testSourceDirectory>src/test/java</testSourceDirectory> 
     <outputDirectory>target/main</outputDirectory> 
     <testOutputDirectory>target/test</testOutputDirectory> 
     <resources> 
      <resource> 
       <targetPath>ch/diction/webportal/resources</targetPath> 
       <directory>src/main/resources</directory> 
      </resource> 
     </resources> 
     <testResources> 
      <testResource> 
       <targetPath>ch/diction/webportal/resources</targetPath> 
       <directory>src/test/resources</directory> 
      </testResource> 
      <testResource> 
       <targetPath>ch/diction/webportal/resources</targetPath> 
       <directory>src/main/resources</directory> 
      </testResource> 
     </testResources> 
     <plugins> 
      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-compiler-plugin</artifactId> 
       <configuration> 
        <source>1.7</source> 
        <target>1.7</target> 
       </configuration> 
      </plugin> 
     </plugins> 
    </build> 

    <repositories> 
     <repository> 
      <id>jboss-public-repository-group</id> 
      <name>JBoss Public Maven Repository Group</name> 
      <url>http://repository.jboss.org/nexus/content/groups/public</url> 
     </repository> 
     <repository> 
      <id>Java.Net</id> 
      <name>Java Maven Repository</name> 
      <url>http://download.java.net/maven/2/</url> 
     </repository> 
     <repository> 
      <id>prime-repo</id> 
      <name>PrimeFaces Maven Repository</name> 
      <url>http://repository.primefaces.org</url> 
      <layout>default</layout> 
     </repository> 
    </repositories> 
    <dependencyManagement> 
     <dependencies> 
      <dependency> 
       <groupId>org.jboss.seam</groupId> 
       <artifactId>seam-bom</artifactId> 
       <version>${seam.version}</version> 
       <type>pom</type> 
       <scope>import</scope> 
      </dependency> 
      <dependency> 
       <groupId>org.jboss.arquillian</groupId> 
       <artifactId>arquillian-bom</artifactId> 
       <version>${arquillian.version}</version> 
       <scope>import</scope> 
       <type>pom</type> 
      </dependency> 
     </dependencies> 
    </dependencyManagement> 
    <dependencies> 
     <dependency> 
      <groupId>org.primefaces</groupId> 
      <artifactId>primefaces</artifactId> 
      <version>${primefaces.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.primefaces.themes</groupId> 
      <artifactId>redmond</artifactId> 
      <version>${primefaces.theme.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.seam.security</groupId> 
      <artifactId>seam-security</artifactId> 
      <scope>compile</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.drools</groupId> 
      <artifactId>drools-core</artifactId> 
      <version>${drools.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.drools</groupId> 
      <artifactId>drools-compiler</artifactId> 
      <version>${drools.version}</version> 
      <exclusions> 
       <exclusion> 
        <groupId>org.drools</groupId> 
        <artifactId>drools-core</artifactId> 
       </exclusion> 
      </exclusions> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.seam.persistence</groupId> 
      <artifactId>seam-persistence</artifactId> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.solder</groupId> 
      <artifactId>solder-impl</artifactId> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.seam.transaction</groupId> 
      <artifactId>seam-transaction</artifactId> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.seam.international</groupId> 
      <artifactId>seam-international-api</artifactId> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.seam.international</groupId> 
      <artifactId>seam-international</artifactId> 
      <scope>runtime</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.seam.faces</groupId> 
      <artifactId>seam-faces</artifactId> 
     </dependency> 
     <!-- Test dependencies --> 
     <dependency> 
      <groupId>junit</groupId> 
      <artifactId>junit</artifactId> 
      <version>${junit.version}</version> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.arquillian.junit</groupId> 
      <artifactId>arquillian-junit-container</artifactId> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.arquillian.container</groupId> 
      <artifactId>arquillian-glassfish-embedded-3.1</artifactId> 
      <version>1.0.0.CR3</version> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.glassfish.main.extras</groupId> 
      <artifactId>glassfish-embedded-all</artifactId> 
      <version>3.1.2</version> 
      <scope>provided</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.slf4j</groupId> 
      <artifactId>slf4j-simple</artifactId> 
      <version>${slf4j.version}</version> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>com.h2database</groupId> 
      <artifactId>h2</artifactId> 
      <version>${h2.version}</version> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.apache.tomcat</groupId> 
      <artifactId>juli</artifactId> 
      <version>6.0.13</version> 
      <scope>test</scope> 
     </dependency> 
    </dependencies> 
</project> 

Je suppose que pour ce poste, seuls les « dépendances d'essai » sont importants (voir marqueur de commentaire), puisque la principale Deploy réelle fonctionne parfaitement. Exécution du test unitaire suivante:

package ch.diction.webportal.test.glossary.model; 

import javax.inject.Inject; 
import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 
import javax.transaction.UserTransaction; 

import org.jboss.arquillian.container.test.api.Deployment; 
import org.jboss.arquillian.junit.Arquillian; 
import org.jboss.seam.security.SecurityInterceptor; 
import org.jboss.seam.transaction.TransactionInterceptor; 
import org.jboss.shrinkwrap.api.Archive; 
import org.jboss.shrinkwrap.api.ShrinkWrap; 
import org.jboss.shrinkwrap.api.spec.WebArchive; 
import org.junit.After; 
import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 

import ch.diction.webportal.glossary.entity.Glossary; 
import ch.diction.webportal.glossary.model.IGlossaryDataAccessObject; 
import ch.diction.webportal.glossary.model.JpaGlossaryDataAccessObject; 
import ch.diction.webportal.security.seam.producer.EntityManagerProducer; 

@RunWith(Arquillian.class) 
public class JpaGlossaryDataAccessObjectTest { 
    @Deployment 
    public static Archive<?> createDeployment() { 
     final Archive<?> ar = ShrinkWrap 
       .create(WebArchive.class, "test.war") 
       .addPackage(Glossary.class.getPackage()) 
       .addClass(SecurityInterceptor.class) 
       .addClass(TransactionInterceptor.class) 
       .addClass(EntityManagerProducer.class) 
       .addClass(JpaGlossaryDataAccessObject.class) 
       .addAsWebInfResource("ch/diction/webportal/resources/security/beans.xml", "beans.xml") 
       .addAsResource("ch/diction/webportal/resources/persistence/persistence.xml", "META-INF/persistence.xml"); 
     return ar; 
    } 

    @Inject 
    private IGlossaryDataAccessObject dao; 
    @PersistenceContext 
    private EntityManager entityManager; 
    @Inject 
    private UserTransaction userTransaction; 

    private void clearData() throws Exception { 
     userTransaction.begin(); 
     entityManager.joinTransaction(); 
     entityManager.createQuery("delete from Glossary").executeUpdate(); 
     userTransaction.commit(); 
    } 

    @After 
    public void commitTransaction() throws Exception { 
     userTransaction.commit(); 
    } 

    private void insertData() throws Exception { 
     userTransaction.begin(); 
     entityManager.joinTransaction(); 
     // TODO: Insert records 
     userTransaction.commit(); 
     entityManager.clear(); 
    } 

    @Before 
    public void preparePersistenceTest() throws Exception { 
     clearData(); 
     insertData(); 
     startTransaction(); 
    } 

    private void startTransaction() throws Exception { 
     userTransaction.begin(); 
     entityManager.joinTransaction(); 
    } 

    @Test 
    public void testCreateEmptyGlossary() { 
     final Glossary glossary = new Glossary("empty"); 
     dao.store(glossary); 
    } 
} 

me donne maintenant à l'exception suivante:

Caused by: java.lang.VerifyError: class com.sun.enterprise.web.WebModule overrides final method stop.()V 
    at java.lang.ClassLoader.defineClass1(Native Method) 
    at java.lang.ClassLoader.defineClass(ClassLoader.java:791) 
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) 
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) 
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356) 
    at java.lang.Class.getDeclaredConstructors0(Native Method) 
    at java.lang.Class.privateGetDeclaredConstructors(Class.java:2404) 
    at java.lang.Class.getConstructor0(Class.java:2714) 
    at java.lang.Class.newInstance0(Class.java:343) 
    at java.lang.Class.newInstance(Class.java:325) 
    at com.sun.hk2.component.ConstructorCreator.create(ConstructorCreator.java:65) 
    ... 79 more 

Quant à cela, je suis complètement désemparés. Je ne savais même pas ce genre d'exceptions existait dans java o.O ...

Merci d'avance pour toute suggestion ici! Toute aide est appréciée!

Cordialement Pascal

Répondre

1

Eh bien, je fini par ignorer la partie h2database et utilisé à la place une base de données de test MySQL fourni par un Glassfish à part entière 3.1.2 conteneur. Le conteneur embarqué de l'Arquillian s'est avéré très compliqué et ne valait pas la peine, quand Arquillian peut travailler avec de vrais conteneurs Glassfish distants à la place.

C'est le POM j'ai fini avec:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 
    <groupId>ch.diction</groupId> 
    <artifactId>web-portal</artifactId> 
    <version>0.0.1-SNAPSHOT</version> 
    <name>Diction web portal</name> 
    <packaging>war</packaging> 

    <properties> 
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
     <jee.version>1.0.0.Final</jee.version> 
     <seam.version>3.1.0.Final</seam.version> 
     <primefaces.version>3.4</primefaces.version> 
     <primefaces.theme.version>1.0.8</primefaces.theme.version> 
     <drools.version>5.4.0.Final</drools.version> 
     <arquillian.version>1.0.2.Final</arquillian.version> 
     <arquillian.persistence.version>1.0.0.Alpha5</arquillian.persistence.version> 
     <junit.version>4.8.1</junit.version> 
     <slf4j.version>1.6.6</slf4j.version> 
    </properties> 

    <build> 
     <sourceDirectory>src/main/java</sourceDirectory> 
     <testSourceDirectory>src/test/java</testSourceDirectory> 
     <outputDirectory>target/main</outputDirectory> 
     <testOutputDirectory>target/test</testOutputDirectory> 
     <resources> 
      <resource> 
       <targetPath>ch/diction/webportal/resources</targetPath> 
       <directory>src/main/resources</directory> 
      </resource> 
     </resources> 
     <testResources> 
      <testResource> 
       <targetPath>ch/diction/webportal/resources</targetPath> 
       <directory>src/test/resources</directory> 
      </testResource> 
      <testResource> 
       <directory>src/test/resources/container</directory> 
      </testResource> 
      <testResource> 
       <targetPath>ch/diction/webportal/resources</targetPath> 
       <directory>src/main/resources</directory> 
      </testResource> 
     </testResources> 
     <plugins> 
      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-compiler-plugin</artifactId> 
       <configuration> 
        <source>1.7</source> 
        <target>1.7</target> 
       </configuration> 
      </plugin> 
     </plugins> 
    </build> 

    <repositories> 
     <repository> 
      <id>jboss-public-repository-group</id> 
      <name>JBoss Public Maven Repository Group</name> 
      <url>http://repository.jboss.org/nexus/content/groups/public</url> 
     </repository> 
     <repository> 
      <id>Java.Net</id> 
      <name>Java Maven Repository</name> 
      <url>http://download.java.net/maven/2/</url> 
     </repository> 
     <repository> 
      <id>prime-repo</id> 
      <name>PrimeFaces Maven Repository</name> 
      <url>http://repository.primefaces.org</url> 
      <layout>default</layout> 
     </repository> 
    </repositories> 
    <dependencyManagement> 
     <dependencies> 
      <dependency> 
       <groupId>org.jboss.seam</groupId> 
       <artifactId>seam-bom</artifactId> 
       <version>${seam.version}</version> 
       <type>pom</type> 
       <scope>import</scope> 
      </dependency> 
      <dependency> 
       <groupId>org.jboss.arquillian</groupId> 
       <artifactId>arquillian-bom</artifactId> 
       <version>${arquillian.version}</version> 
       <scope>import</scope> 
       <type>pom</type> 
      </dependency> 
     </dependencies> 
    </dependencyManagement> 
    <dependencies> 
     <dependency> 
      <groupId>org.primefaces</groupId> 
      <artifactId>primefaces</artifactId> 
      <version>${primefaces.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.primefaces.themes</groupId> 
      <artifactId>redmond</artifactId> 
      <version>${primefaces.theme.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.seam.security</groupId> 
      <artifactId>seam-security</artifactId> 
      <scope>compile</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.drools</groupId> 
      <artifactId>drools-core</artifactId> 
      <version>${drools.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.drools</groupId> 
      <artifactId>drools-compiler</artifactId> 
      <version>${drools.version}</version> 
      <exclusions> 
       <exclusion> 
        <groupId>org.drools</groupId> 
        <artifactId>drools-core</artifactId> 
       </exclusion> 
      </exclusions> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.seam.persistence</groupId> 
      <artifactId>seam-persistence</artifactId> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.solder</groupId> 
      <artifactId>solder-impl</artifactId> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.seam.transaction</groupId> 
      <artifactId>seam-transaction</artifactId> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.seam.international</groupId> 
      <artifactId>seam-international-api</artifactId> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.seam.international</groupId> 
      <artifactId>seam-international</artifactId> 
      <scope>runtime</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.seam.faces</groupId> 
      <artifactId>seam-faces</artifactId> 
     </dependency> 
     <!-- Test dependencies --> 
     <dependency> 
      <groupId>org.jboss.spec</groupId> 
      <artifactId>jboss-javaee-6.0</artifactId> 
      <version>${jee.version}</version> 
      <type>pom</type> 
      <scope>provided</scope> 
     </dependency> 
     <dependency> 
      <groupId>junit</groupId> 
      <artifactId>junit</artifactId> 
      <version>${junit.version}</version> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.arquillian.junit</groupId> 
      <artifactId>arquillian-junit-container</artifactId> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.arquillian.container</groupId> 
      <artifactId>arquillian-glassfish-remote-3.1</artifactId> 
      <version>1.0.0.CR3</version> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.arquillian.extension</groupId> 
      <artifactId>arquillian-persistence-impl</artifactId> 
      <version>${arquillian.persistence.version}</version> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.jboss.shrinkwrap.resolver</groupId> 
      <artifactId>shrinkwrap-resolver-impl-maven</artifactId> 
      <scope>test</scope> 
     </dependency> 
    </dependencies> 
</project> 

Et mon test-persistence.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" 
    version="2.0"> 
    <persistence-unit name="web-portal-test" transaction-type="JTA"> 
     <jta-data-source>jdbc/web-portal-test</jta-data-source> 
     <properties> 
      <property name="eclipselink.logging.level" value="FINE" /> 
     </properties> 
    </persistence-unit> 
</persistence> 

La leçon que je reçois de ce que Arquillian est bord trop saigne pour provoquer problèmes de configuration inutiles. À partir de maintenant, je commencerai toujours avec un conteneur distant complet.

+0

Je pense que le problème est plutôt que le conteneur intégré partage le même classpath avec toutes vos autres dépendances, ce qui peut provoquer de tels problèmes. Par exemple, avec GlassFish intégré, vous devez également faire attention à Google Goyave :) Les gars d'Arquillian sont conscients de ces limitations et il existe un effort continu pour rendre les problèmes de chargement de classes moins pénibles pour les conteneurs intégrés. –

+1

Un autre avantage d'avoir un conteneur distant est que vous gagnez du temps pour l'amorcer pour chaque classe de test => feedback plus rapide. –

Questions connexes