Skip to content
Qaiser Abbasi edited this page Jan 20, 2015 · 20 revisions

This page contains a list of various testing scenarios implemented with CDI BeanTesting.

Note: Import statements are intentionally missing.

Provide a mock instance in the test environment

As already described in the Quick Start section, depending on your project configuration it could occur that certain bean definitions are not directly injectable by the CDI BeanContainer e.g. @Remote view beans. For that purpose you can provide mock instances via CDI producer methods/fields for a successful test execution. This technique is also useful if you want to test only a certain number of components.

public class MockProvider {
  @Produces static final Service service = mock(Service);
}

Testing the persistence layer (JPQL queries & Bean Validation constraints)

How many times you simply wanted to test if a update in a JPQL query or custom defined BeanValidation constraint worked out as expected? That´s history now. With the help of CDI BeanTesting you can instantly (approx. unit test feedback level) test your changes. Better yet, now you can practise TDD, while developing Java EE applications!
CDI BeanTesting already provides out of the box transaction handling and Bean Validation functionalities.

Sample entity definition including a Bean Validation constraint

@Entity
public class MyEntityWithConstraints {
    
  @Column(unique = true)
  private String uniqueValue;
}

Testing the Bean Validation constraint

@Test(expected = PersistenceException.class)
public void shouldCauseExceptionBecuaseUniquenessViolation() {
   MyEJBService myEJBService = getBean(MyEJBService.class);
   MyEntityWithConstraints entity = new MyEntityWithConstraints("123");
   myEJBService.save(entity);
   entity = new MyEntityWithConstraints("123");
   myEJBService.save(entity);
   fail("Should have failed because of uniqueness violation");
}

How to test Interceptors

In normal unit testing there is no chance to test the successful Interceptor invocation respectively the action during the test execution. The reason for it are the missing container services, which normally are only provided by the Java EE Application server at runtime. Again CDI BeanTesting provides a convenient solution for it.

Sample EJB and Interceptor constellation

public class InterceptorPersistingEntity {

    @Inject
    EntityManager entityManager;

    @AroundInvoke
    public Object handle(InvocationContext context) throws Exception {
        entityManager.persist(new MyEntity());
        return context.proceed();
    }
}

@Stateless
@Interceptors(value = InterceptorPersistingEntity.class)
public class EJBInterceptedByMultipleInterceptors {

    @PersistenceContext
    EntityManager entityManager;

    public void business() {}

    public int getPersistedEntitiesCount() {
        CriteriaQuery<MyEntity> createQuery = entityManager.getCriteriaBuilder().createQuery(MyEntity.class);
        Root<MyEntity> from = createQuery.from(MyEntity.class);
        CriteriaQuery<MyEntity> select = createQuery.select(from);
        return entityManager.createQuery(select).getResultList().size();
    }

Testing the successful Interceptor invocation

@Test
public void business_service_call_should_invoke_surrounding_interceptors() {
   EJBInterceptedByMultipleInterceptors bean = getBean(EJBInterceptedByMultipleInterceptors.class);
   bean.business();
   assertThat(bean.getPersistedEntitiesCount(), is(2));
}

Testing services backed by CDI Events

Imagine you have a business service 'RegistrationService' which handles the registration of new users in a system. As part of the functional requirement the service sends a confirmation email to newly registered users. Therefor the service uses an another service called 'MessagingService', which actually sends the confirmation mail to the user.
Technically 'RegistrationService' triggers a domain-specific CDI Event in order to inform potentially interested components about the new registration in the system. In this example the component is called 'RegistrationObserver'.

So the interesting test object here is the successful CDI event-based activation of the observer component. Furthermore as already explained in the first item 'Provide a mock instance', CDI BeanTesting allows to mock certain components in the test environment in order to abstract the testing level. In our example we don´t want to test if the 'MessagingService' actually sent a confirmation mail to the user, because this would significantly exceed the test execution time respectively it is at least hard to determine if the user actually received the confirmation mail.

Sample service and CDI event/observer components

public class User {***}

public class RegistrationEvent {
  User user;

  public RegistrationEvent(User user) {
    this.user = user;
  }
}

public class RegistrationService {
  @Inject Event<RegistrationEvent> registrationEvent;

  public void register(User user) {
     ***
     registrationEvent.fire(new RegistrationEvent(user));
     ***
  }
}

public class RegistrationObserver {

  @Inject MessagingService messagingService;

  public void onUserRegistration(@Observes RegistrationEvent event) {
    messagingService.sendEmail(event.getUser().getEmail());
  }
}

public class MessagingService {***}

Testing the CDI event-based service using a mock instance

public class MockProvider {
  @Produces final static MessagingService service = mock(MessagingService.class);
}

@Test
public when_new_user_registrates_registration_event_should_be_fired() {
  RegistrationService service = getBean(RegistrationService.class);
  service.register(new User("a@b");
  verify(MockProvider.service).sendEmail("a@b");
}