You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JUnit 5+EE8环境下SE测试通过CDI获取替代EntityManager咨询

解决方案:激活CDI替代并在JUnit 5 SE测试中获取Mock EntityManager

你的核心问题是没有正确激活自定义的MockResources替代类,反而错误地在beans.xml中指定了Hibernate的SessionImpl,这完全不符合CDI替代的规则。下面是一步步的修正方案:


1. 修正MockResources的注解配置

首先调整你的MockResources,确保它的作用域和替代标识匹配原生产者的配置,避免CDI容器出现歧义:

import javax.enterprise.inject.Alternative;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;

@Alternative // 标记为CDI替代类
@ApplicationScoped // 和原Resources的作用域保持一致
public class MockResources {

    @Produces
    public EntityManager getEntityManager() {
        // 建议使用测试专用的PU(比如内存H2数据库),避免污染生产数据
        return Persistence.createEntityManagerFactory("primary-test")
                          .createEntityManager();
    }
}

提示:如果坚持用primary PU,请确保测试时连接的是测试数据库,而非生产库。


2. 配置测试专用的beans.xml

在测试资源目录下创建src/test/resources/META-INF/beans.xml,专门用于激活你的替代类,不要修改主程序的beans.xml:

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

    <!-- 激活自定义的MockResources替代类 -->
    <alternatives>
        <class>你的实际包路径.MockResources</class> <!-- 替换成真实的全类名 -->
    </alternatives>
</beans>

这里的关键是:CDI的@Alternative是用来替换整个bean/生产者类,而非底层实现类,所以你要激活的是自己写的MockResources,不是Hibernate的SessionImpl。


3. 在JUnit 5测试中获取CDI管理的EntityManager

要在SE环境的JUnit测试中使用CDI,需要引入Weld SE容器和JUnit 5扩展,实现依赖注入:

3.1 添加测试依赖(Maven示例)

在pom.xml中加入以下依赖:

<dependencies>
    <!-- JUnit 5核心依赖 -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.9.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.9.2</version>
        <scope>test</scope>
    </dependency>
    <!-- Weld SE:SE环境下的CDI容器 -->
    <dependency>
        <groupId>org.jboss.weld.se</groupId>
        <artifactId>weld-se-core</artifactId>
        <version>4.0.3.Final</version>
        <scope>test</scope>
    </dependency>
    <!-- Weld JUnit 5扩展:让JUnit测试支持CDI注入 -->
    <dependency>
        <groupId>org.jboss.weld.junit5</groupId>
        <artifactId>weld-junit5</artifactId>
        <version>4.0.3.Final</version>
        <scope>test</scope>
    </dependency>
</dependencies>

3.2 编写JUnit 5测试类

使用@EnableWeld启动CDI容器,直接注入EntityManager即可:

import org.junit.jupiter.api.Test;
import org.jboss.weld.junit5.EnableWeld;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import static org.junit.jupiter.api.Assertions.assertNotNull;

@EnableWeld // 启动Weld CDI容器
public class EntityManagerMockTest {

    @Inject
    private EntityManager entityManager; // 这里会自动注入MockResources生产的实例

    @Test
    void testEntityManagerInjection() {
        assertNotNull(entityManager);
        // 在这里编写你的业务测试逻辑,比如持久化测试实体、查询验证等
    }
}

关键原理说明

  • CDI的@Alternative是候选替代类,必须在beans.xml中显式激活才会覆盖原bean。
  • 测试环境使用独立的beans.xml,可以避免测试配置影响生产代码。
  • Weld SE和JUnit 5扩展让SE环境也能完整使用CDI的依赖注入能力,完美适配你的测试场景。

内容的提问来源于stack exchange,提问作者Fabrizio Stellato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 13:32:47