CDI:beans.xml 在与 Arquillian 集成测试期间未在 EJB 项目中使用

CDI: beans.xml not used in an EJB project during integration testing with Arquillian

我正在尝试使用显式 CDI 创建一个 Java EE 7 项目。项目被Maven打包为ejb项目

尽管 Java EE 7 不再需要 beans.xml,但我有一个这样的文件,位于 src/main/resources/META-INF/beans.xml 下,因为我想使用 @Alternatives 进行测试。

更准确地说,我想在集成测试期间使用 H2 内存数据库(使用 Arquillian 和 Weld),但对于非本地环境来说是一个很好的 'ol Postgres 数据库。

我的问题:

beans.xml 文件似乎被忽略了。测试:

org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [EntityManager] with qualifiers [@Default] at injection point [[field] @Inject private arquillian.ArquillianTestAbstract.em]

我觉得 beans.xml 是在错误的地方什么的,但我到处搜索(包括 this related question on SO),我找不到我的错误。

一些文件:

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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>
    <parent>
        <groupId>com.mystuff</groupId>
        <artifactId>myparent</artifactId>
        <version>${project-version}</version>
    </parent>
    <artifactId>myproject</artifactId>
    <packaging>ejb</packaging>

(snip - various dependencies)       

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-ejb-plugin</artifactId>
                    <version>${ejb-plugin-version}</version>
                    <configuration>
                        <ejbVersion>${ejb-version}</ejbVersion>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>${surefire-plugin-version}</version>
                    <configuration>
                        <argLine>-Dfile.encoding=UTF-8</argLine>
                        <forkCount>1C</forkCount>
                        <redirectTestOutputToFile>false</redirectTestOutputToFile>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>  
    </build>

</project>

src/main/resources/META-INF/beans.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       bean-discovery-mode="all" version="1.1"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd">

    <alternatives>
        <class>persistence.TestDatabaseProducer</class>
    </alternatives>

</beans> 

src/main/java/persistence/DatabaseProducerImpl.java:

@Singleton
@Alternative
public class DatabaseProducerImpl implements DatabaseProducer {

    @Produces
    @MyDatabase
    @Override
    public EntityManager createEntityManager() {
        return Persistence.createEntityManagerFactory("primary").createEntityManager();
    }

}

src/main/java/persistence/TestDatabaseProducer.java:

@Singleton
@Alternative
public class TestDatabaseProducer implements DatabaseProducer {

    @Produces
    @InternalDatabase
    @Override
    public EntityManager createEntityManager() {
        return Persistence.createEntityManagerFactory("internal").createEntityManager();
    }

}

结果我找错了方向。 beans.xml 文件没有任何问题,只是在测试期间没有考虑到它。

这是通过 Arquillian 对 Weld 的测试所特有的,并且由于资产被打包并发送到嵌入式容器的方式。

Arquillian 测试的标准做法鼓励使用 ShrinkWrap 创建部署在 Weld 上的 JavaArchive,如果您不要求,ShrinkWrap 不会启动 beans.xml

此代码解决了问题:(具体来说,.addAsManifestResource() 调用)

@Deployment
public static JavaArchive createDeployment() {
    final BeansDescriptor beansXml = Descriptors.create(BeansDescriptor.class);

    return ShrinkWrap.create(JavaArchive.class)
        .addPackages(true, "persistence")
        .addAsManifestResource(new StringAsset(beansXml.alternativeClass(TestDatabaseProducer.class).exportAsString()), beansXml.getDescriptorName());
}