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.
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.