使用 spring 测试 EJB 拦截器

Testing EJB interceptor using spring

我想测试(使用功能测试)被 EJB Iterceptor 拦截的 EJB 服务。此应用程序 运行 在 WildFly 服务器上。

测试:

@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() {
      //...
    }
  }
}

服务:

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

  //...

}

拦截器:

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

我的测试设法测试了服务、DAO 和映射器,但根本没有调用拦截器。我猜这是因为我在 Spring 测试中使用了 JavaEE 拦截器,但我不知道如何让它工作。 我正在使用 Spring 4.3 和 JavaEE 7。

我使用 weld-junit4 来使用 weld 作为容器而不是 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();
  }
}

通过这种方式,我能够对 @Interceptors@Inject 使用 JavaEE 注入,并使用 Spring 使用 H2 模拟数据库。