0

我目前正在解决使用 Arquillian 创建数据库单元测试环境的许多问题。我的项目已经在基于 Seam 3、JSF 和 MySQL 的 Glassfish 3.1.2 环境中运行。但是,当尝试使用 Arquillian 设置测试环境时,事情变得很糟糕。

我的最终目标是使用 Glassfish 嵌入式服务器和嵌入式内存 h2 数据库进行基于 Arquillian 的单元测试。对于嵌入式容器,我并不挑剔,只是 Arquillian JPA 指南建议最小的 Weld 容器不支持 JPA。这就是我选择 Glassfish 的原因。由于我还没有接近持久性上下文的初始化,所以我没有发布我的 persistence.xml 文件。

到目前为止,这是我最终得到的 POM:

<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>

我想对于这篇文章,只有“测试依赖项”很重要(见评论标记),因为实际的主要部署完美无缺。运行以下单元测试:

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);
    }
}

现在为我提供了以下例外:

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

对此,我完全一无所知。我什至不知道java oO中存在这些类型的异常......

在此先感谢您的任何建议!任何帮助表示赞赏!

最好的问候帕斯卡

4

1 回答 1

1

好吧,我最终忽略了 h2database 部分,而是使用了一个由成熟的 Glassfish 3.1.2 容器提供的 MySQL 测试数据库。当 Arquillian 可以使用实际的远程 Glassfish 容器代替时,Arquillian 的嵌入式容器被证明相当麻烦并且不值得麻烦。

这是我最终得到的 POM:

    <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>

还有我的 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>

The lesson I get from this is that Arquillian is too bleeding edge to provoke unnecessary configuration issues. From now on, I'll always start out with a full remote container.

于 2012-10-04T12:11:43.120 回答