Search code examples
ejbinterceptorspring-testjava-ee-7

Testing EJB interceptor using spring


I want to test (using functional testing) a EJB service that is being intercepted by an EJB Iterceptor. This application is running on a WildFly server.

The test:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {FooServiceTest.ClassContextTest.class})
public class FooServiceTest {

  @Autowired public FooServiceImpl service;

  @Test
  public void createTest() throws Exception {
    Foo foo = new Foo();
    // ...
    service.create(foo);
    // ...
  }

  @Configuration
  public static class ClassContextTest {
    @Bean
    public FooServiceImpl produceService() {
      return new FooServiceImpl();
    }

    @Bean
    public FooDao produceDao() {
      //...
    }
  }
}

The service:

@Stateless
@Interceptors({ValidationInterceptor.class})
public class FooServiceImpl implements FooService {

  private FooDao dao;

  @Inject
  public void setDao(FooDao dao) {
    this.dao = dao;
  }

  public void create(@Valid Foo foo) {
    // ...
    dao.create(foo);
    // ...
  }

  //...

}

the interceptor:

public class ValidationInterceptor {

  private Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

  @AroundInvoke
  public Object intercept(InvocationContext ctx) throws Exception {

    Object[] paramValues = ctx.getParameters();
    Parameter[] params = ctx.getMethod().getParameters();
    for (int i = 0; i < params.length; i++) {
      if (params[i].isAnnotationPresent(Valid.class)) {
        Object value = paramValues[i];
        valid(value);
      }
    }
    return ctx.proceed();
  }

  private void valid(Object value) throws ConstraintViolationException {
    Set<ConstraintViolation<Object>> violations = validator.validate(value);
    if (!violations.isEmpty()) {
      Set<ConstraintViolation<?>> cvs = new HashSet<>();
      for (ConstraintViolation<?> cv : violations) {
        cvs.add(cv);
      }
      throw new ConstraintViolationException(cvs);
    }
  }
}

My test managed to test the service, the DAO and the mapper but the interceptor is not called at all. I am guessing it's because I use an JavaEE interceptor in a Spring test but I have no idea how to make that working. I am using Spring 4.3 and JavaEE 7.


Solution

  • I used weld-junit4 to use weld as a ontainer instead of Spring.

    public class FooServiceTest {
      @Rule
      public WeldInitiator weld = WeldInitiator.from(FooServiceImpl.class, this.getClass()).build();
    
      public FooServiceImpl service;
    
      private static DataSource ds;
    
      @BeforeClass
      public static void beforeClass() {
        ds = h2DataSource();
      }
    
      @Test
      public void createTest() throws Exception {
        Foo foo = new Foo();
        // ...
        service.create(foo);
        // ...
      }
    
      @Produces
      public FooDao produceDao() {
        FooDao dao = new FooDao() {};
        dao.setDataSource(ds);
        return dao;
      }
    
      public static DataSource h2DataSource() {
        return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).addScript("my/path/scripts.sql").build();
      }
    }
    

    This way I was able to use JavaEE injection for @Interceptors and @Inject and use Spring to mock the database using H2.