CDI:从JUnit测试调用时不调用Interceptor

时间:2014-06-16 19:55:03

标签: java jboss weld weld-se

我在JBoss documentation之后创建了一个拦截器。

为了测试拦截器,我把:

@Interceptor
@Transactional
public class TransactionalInterceptor {
  @AroundInvoke
  public Object intercept(InvocationContext ctx) throws Exception {
    System.out.println("intercept!");
    return ctx.proceed();
  }
}

现在我想使用the WeldJUnit4Runner class在单元测试中测试此拦截器。

@RunWith(WeldJUnit4Runner.class)
public class MyTest {
  @Test
  @Transactional  // the interceptor I created
  public void testMethod() {
    System.out.println("testMethod");
    anotherMethod();
  }

  @Transactional
  public void anotherMethod() {
    System.out.println("anotherMethod");
  }
}

现在预期的输出当然是

intercept!
testMethod
intercept!
anotherMethod

但相反,输出是

intercept!
testMethod
anotherMethod

主要的问题是,如果我在我的测试中注入一个bean也是如此:我调用的bean的第一个方法被拦截,但是如果这个方法调用另一个方法,则不会调用拦截器。

任何想法都非常感谢!


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

@RunWith(WeldJUnit4Runner.class)
public class MyTest {
  @Inject
  private MyTest instance;

  @Test
  @Transactional  // the interceptor I created
  public void testMethod() {
    System.out.println("testMethod");
    instance.anotherMethod();
  }

  @Transactional
  public void anotherMethod() {
    System.out.println("anotherMethod");
  }
}

输出是(正如预期的那样)

intercept!
testMethod
intercept!
anotherMethod

然而,以下工作:

@RunWith(WeldJUnit4Runner.class)
public class MyTest {
  @Inject
  private MyTest instance;

  @Test
  // @Transactional  <- no interceptor here!
  public void testMethod() {
    System.out.println("testMethod");
    instance.anotherMethod();
  }

  @Transactional
  public void anotherMethod() {
    System.out.println("anotherMethod");
  }
}

这里的输出是

testMethod
anotherMethod

然而,这似乎是根据规范!一切都很好。

2 个答案:

答案 0 :(得分:2)

拦截器是使用代理实现的。由于第二个方法是从对象实例中调用的,因此代理无法捕获该调用,因此无法拦截该调用。您需要引用bean的CDI代理才能这样做。

答案 1 :(得分:-1)

可以使用DeltaSpike在正确初始化的CDI bean上运行测试,尽管它的文档和错误消息在它不完全正确时不是很有用。这是为了让@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

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

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