Weld-Junit5中addPackages无法将包内所有Bean加入测试容器的问题
正在从Java EE 8迁移到Jakarta EE 10,使用Weld进行JUnit 5测试时遇到问题:Weld无法解析被注入的ExampleHelper类,报错WELD-001408: Unsatisfied dependencies。
示例代码
Example类(注入ExampleHelper)
public class Example { @Inject ExampleHelper exampleHelper; public void getHelloText() { exampleHelper.greet(); } }
ExampleHelper类
public class ExampleHelper { public void greet() { System.out.println("Hello"); } }
JUnit 5测试类
@ExtendWith(WeldJunit5Extension.class) class ExampleTest { @WeldSetup public WeldInitiator weld = WeldInitiator.of(WeldInitiator.createWeld() .addBeanClass(Example.class) .addPackages(false, Example.class.getPackage()) ); @Inject Example example; @Test public void test() { example.getHelloText(); } }
报错信息
org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type ExampleHelper with qualifiers @Default at injection point [BackedAnnotatedField] @Inject com.company.wf28test.Example.exampleHelper at com.company.wf28test.Example.exampleHelper(Example.java:0)
依赖版本
jakarta.jakartaee-api 10.0.0 junit-jupiter-api 5.9.3 junit-jupiter-engine 5.9.3 weld-junit5 4.0.0.Final
原本以为调用addPackages(false, Example.class.getPackage())会扫描包内所有类并识别为CDI bean(Java EE 8中这么做没问题),但只有显式用addBeanClass逐个添加被注入类才能正常运行,想知道问题出在哪。
问题核心在于Weld 4.x(对应Jakarta EE 10)的JUnit扩展对addPackages方法的参数逻辑做了调整,和Java EE 8时期的Weld版本行为不同:
addPackages参数的含义变化
你传入的addPackages(false, ...)里的false,表示不扫描包内无CDI注解的类。而你的ExampleHelper是没有任何CDI注解的普通类,所以Weld不会自动把它识别为CDI bean。
在Java EE 8的Weld版本中,addPackages默认会扫描包内所有类,不管有没有注解,但Weld 4.x为了测试轻量化,调整了这个逻辑:只有当scanAnnotated参数为true时,才会扫描包内所有类(包括无注解的隐式bean);传false时,只注册显式添加的类和带CDI注解的类。CDI 3.0的隐式bean规则
虽然Jakarta EE 10的CDI 3.0仍然支持无注解的隐式bean,但Weld的JUnit扩展不会自动扫描这类bean,必须明确配置。
两种修复方式
- 方式一:修改
addPackages参数为true
把addPackages(false, Example.class.getPackage())改成addPackages(true, Example.class.getPackage()),让Weld扫描包内所有类,包括无注解的ExampleHelper:
@ExtendWith(WeldJunit5Extension.class) class ExampleTest { @WeldSetup public WeldInitiator weld = WeldInitiator.of(WeldInitiator.createWeld() .addBeanClass(Example.class) .addPackages(true, Example.class.getPackage()) ); @Inject Example example; @Test public void test() { example.getHelloText(); } }
- 方式二:给
ExampleHelper添加CDI注解
给ExampleHelper加上@Named或@Singleton等CDI注解,这样即使scanAnnotated为false,Weld也会识别它为bean:
@Named public class ExampleHelper { public void greet() { System.out.println("Hello"); } }
内容的提问来源于stack exchange,提问作者Iceplanet

