Java CDI:当从JUnit测试调用拦截器时,不会调用拦截器

Java CDI:当从JUnit测试调用拦截器时,不会调用拦截器,java,jboss,weld,weld-se,Java,Jboss,Weld,Weld Se,我已经创建了一个拦截器 为了测试拦截器,我将: @拦截器 @交易的 公共类事务拦截器{ @阿隆登沃克 公共对象截获(InvocationContext ctx)引发异常{ System.out.println(“拦截!”); 返回ctx.procedure(); } } 现在我想在单元测试中测试这个拦截器,使用 @RunWith(WeldJUnit4Runner.class) 公共类MyTest{ @试验 @事务//我创建的拦截器 公共void testMethod(){ System.out

我已经创建了一个拦截器

为了测试拦截器,我将:

@拦截器
@交易的
公共类事务拦截器{
@阿隆登沃克
公共对象截获(InvocationContext ctx)引发异常{
System.out.println(“拦截!”);
返回ctx.procedure();
}
}
现在我想在单元测试中测试这个拦截器,使用

@RunWith(WeldJUnit4Runner.class)
公共类MyTest{
@试验
@事务//我创建的拦截器
公共void testMethod(){
System.out.println(“测试方法”);
anotherMethod();
}
@交易的
公共无效无热法(){
System.out.println(“anotherMethod”);
}
}
现在的预期产出当然是

intercept!
testMethod
intercept!
anotherMethod
但是,结果是相反的

intercept!
testMethod
anotherMethod
主要的问题是,如果我将bean注入到测试中,这也是正确的:我调用的bean的第一个方法被截获,但是如果这个方法调用另一个方法,截获器就不会被调用

任何想法都非常感谢


我只是尝试按照@adrobisch的建议修改我的代码,这是有效的:

@RunWith(WeldJUnit4Runner.class)
公共类MyTest{
@注入
私有MyTest实例;
@试验
@事务//我创建的拦截器
公共void testMethod(){
System.out.println(“测试方法”);
instance.anotherMethod();
}
@交易的
公共无效无热法(){
System.out.println(“anotherMethod”);
}
}
输出为(如预期的那样)

但是,以下操作不起作用:

@RunWith(WeldJUnit4Runner.class)
公共类MyTest{
@注入
私有MyTest实例;
@试验

//@Transactional拦截器是使用代理实现的。由于第二个方法是从对象实例中调用的,因此代理无法捕获该调用,因此无法拦截该调用。要执行此操作,您需要对bean的CDI代理进行引用。

可以使用Delta在正确初始化的CDI bean上运行测试Spike,虽然它的文档和错误消息在它不完全正确时没有太大帮助。这是如何让@Transactional拦截器工作的:

@Transactional // the @Transactional from org.apache.deltaspike.jpa.api.transaction
@TestControl(startScopes = { TransactionScoped.class })
@RunWith(CdiTestRunner.class)
public MyTestClass { ... }
然后添加:

deltaspike.testcontrol.use_test_class_as_cdi_bean=true
到src/test/resources/META-INF/apache-deltaspike.properties

不幸的是,@Transactional(readOnly=true)不起作用-不知道为什么。而且,与Spring等价物不同,它不会回滚事务,也不会在同一事务中运行@Before/@After


但是对于另一个拦截器,您只需要测试方法本身就可以了。

非常感谢!使用这些信息,我也发现了同样的问题。您是否知道某种工具可以告知源代码中使用这些不正确方法调用的位置?我不会将这些调用称为不正确,它们只是bean中的一个业务方法调用。工具很难检测到这些调用(考虑缺少拦截器注释的接口等)因此,您只需考虑在何处应用拦截器并相应地创建客户端bean。我对编辑中的行为进行了一些研究,我认为从CDI的角度来看,调用
testMethod
中的
anotherMethod
被视为业务方法调用,因此不会应用拦截器。有关详细信息,请参阅CDI spec.TestControl的进一步引用和链接仅控制标准CDI上下文。@事务性(readOnly=true)如果您认为需要处理通过TestControl处理的事务,则无法工作,因为在这种情况下,处理这两个事务的拦截器都不是活动的。如果您使用的是Weld,请确保在测试模块中也启用了事务拦截器。。。
@Transactional // the @Transactional from org.apache.deltaspike.jpa.api.transaction
@TestControl(startScopes = { TransactionScoped.class })
@RunWith(CdiTestRunner.class)
public MyTestClass { ... }
deltaspike.testcontrol.use_test_class_as_cdi_bean=true