我目前在使用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 o.O中存在这些异常......
提前感谢您的任何建议!任何帮助表示赞赏!
祝你好运 帕斯卡
答案 0 :(得分: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>
我从中得到的教训是,Arquillian过于尖锐,无法引发不必要的配置问题。从现在开始,我将始终使用完整的远程容器。