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
相关产品推荐
相关产品推荐

