Search code examples
javajbossweldweld-se

CDI: Interceptor is not invoked when called from a JUnit test


I have created an interceptor following the JBoss documentation.

To test the interceptor, I put:

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

Now I wanted to test this interceptor in a unit test, using 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");
  }
}

Now the expected output would of course be

intercept!
testMethod
intercept!
anotherMethod

But instead, the output is

intercept!
testMethod
anotherMethod

The main problem is that this is also true if I inject a bean into my test: The first method of the bean that I call gets intercepted, but if this method calls another method, the interceptor is not invoked.

Any ideas at all are much appreciated!


I just tried to modify my code as suggested by @adrobisch, and this works:

@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");
  }
}

The output is (as expected)

intercept!
testMethod
intercept!
anotherMethod

However, the following does not work:

@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");
  }
}

The output here is

testMethod
anotherMethod

This seems to be according to spec, however! Everything is fine now.


Solution

  • Interceptors are implemented using proxies. Since the second method is called from within the object instance, the call can't be catched by the proxy and so it can't be intercepted. You would need a reference to the CDI proxy of your bean to do so.