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

Jakarta EE环境下JerseyTest中CDI无法正常工作的问题求助

解决JerseyTest中CDI多容器冲突及依赖注入失效问题

核心问题分析

日志显示多个Weld容器同时运行,导致CDI.current()无法正确定位到管理应用Bean的容器,进而抛出UnsatisfiedResolutionException。这通常是因为JerseyTest测试框架与应用自身的CDI初始化逻辑重复创建了容器实例。

具体解决方案

1. 统一依赖,使用Jersey官方CDI测试扩展

确保项目依赖中引入Jersey的CDI测试支持,避免单独引入Weld SE导致容器重复初始化:

<dependencies>
    <!-- Jersey Test Framework核心 -->
    <dependency>
        <groupId>org.glassfish.jersey.test-framework</groupId>
        <artifactId>jersey-test-framework-core</artifactId>
        <version>${jersey.version}</version>
        <scope>test</scope>
    </dependency>
    <!-- Jersey CDI测试容器 -->
    <dependency>
        <groupId>org.glassfish.jersey.test-framework.providers</groupId>
        <artifactId>jersey-test-framework-provider-cdi</artifactId>
        <version>${jersey.version}</version>
        <scope>test</scope>
    </dependency>
    <!-- 排除重复的Weld依赖(如果存在) -->
    <dependency>
        <groupId>org.jboss.weld.se</groupId>
        <artifactId>weld-se-core</artifactId>
        <version>${weld.version}</version>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.jboss.weld</groupId>
                <artifactId>weld-core-impl</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

2. 配置JerseyTest使用CDI感知的测试容器

在测试类中指定使用CdiTestContainerFactory,确保测试框架统一管理CDI容器:

import org.glassfish.jersey.test.framework.JerseyTest;
import org.glassfish.jersey.test.framework.TestContainerFactory;
import org.glassfish.jersey.test.framework.providers.cdi.CdiTestContainerFactory;

public class UserResourceTest extends JerseyTest {

    @Override
    protected TestContainerFactory getTestContainerFactory() {
        // 强制使用CDI测试容器
        return new CdiTestContainerFactory();
    }

    // 其他测试配置和方法...
}

3. 替换CDI.current()为依赖注入

避免手动调用CDI.current().select(...),改为在测试类中通过@Inject直接注入所需Bean:

import javax.inject.Inject;
import org.junit.jupiter.api.Test;

public class UserResourceTest extends JerseyTest {

    @Inject
    private UserRepository userRepository;

    @Test
    public void testUserRepositoryInjection() {
        // 直接使用注入的实例,无需手动获取
        assert userRepository != null;
    }
}

4. 确保CDI Bean和EntityManager生产者被正确扫描

检查Resources类的EntityManager生产者方法是否正确标注CDI注解,且测试环境能扫描到该类:

import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

public class Resources {

    @PersistenceContext(unitName = "testPU")
    private EntityManager em;

    @Produces
    @RequestScoped
    public EntityManager produceEntityManager() {
        return em;
    }
}

同时,确保测试用persistence.xml放置在src/test/resources/META-INF下,且持久化单元配置与测试环境匹配。

5. 强制单一Weld容器实例

如果上述方法仍未解决,可在测试启动前手动初始化Weld容器并绑定到当前上下文:

import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;

public class UserResourceTest extends JerseyTest {

    private static Weld weld;
    private static WeldContainer container;

    @BeforeAll
    public static void initWeld() {
        weld = new Weld();
        container = weld.initialize();
        // 绑定容器到CDI.current()上下文
        System.setProperty("org.jboss.weld.environment.container.class", "org.jboss.weld.environment.se.Weld");
    }

    @AfterAll
    public static void shutdownWeld() {
        weld.shutdown();
    }

    // 测试方法中通过容器获取Bean
    @Test
    public void testUserRepository() {
        UserRepository repo = container.select(UserRepository.class).get();
        assert repo != null;
    }
}

内容的提问来源于stack exchange,提问作者Håkan Gleissman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 05:35:53