Our current project uses JSF and CDI for the presentation layer. The business logic is encapsulated inside EJB with no-interface view as proposed by Adam Bien and others. I evaluated different alternatives for integration testing and ended up with Arquillian. For JSF/CDI based applications Arquillian is the best fit.
As I digged a little bit deeper into Arquillian one big problem occured: The usage of no-interface EJBs did not allow me to inject some CDI alternatives through the @Alternative annotation. @Alternative expects an interface which I did not have. In addition I had to use the @EJB annotation in the JSF backing bean because our target application server was WebSphere. Since the EJB container, for example JBoss for integration testing, expects all fields annotated with @EJB to be resolved and deployed, I would have to deploy the EJB with all its dependencies. In the end the whole application had to be deployed including database access and without being able to manipulate the result of the EJB methods.
Our data access layer uses JPA/Hibernate but can not make use of “plain” JQL because we had to access legacy stored procedures of an already existing Oracle database – in-memory testing with H2 or Derby was not possible. Another problem would have been the total duration of the integration tests. Our application has a certain complexity and with proceeding project progress the integration tests could not be executed any longer in an acceptable time span.
The only option would have been to switch from no-interface EJBs back to traditional @Local EJBs/interfaces. In the integration tests I would define a stub which implements the interface and deploy the stub with Arquillian. Nevertheless, dynamically controlling the behavior of this stub is not directly possible and I had to write a lot of stubs.
The whole situation did not make me happy. Doing integration tests with Arquillian should force me to change the architecture and introduce more complexity? This was an option I was unwilled to choose and so I searched for alternatives. Surprisingly, Google did not provided any solution. I thought about the problem again and had an idea: I could modify the Java bytecode of the EJB class before it is deployed. The modified EJB would only act as a facade and delegates every method call to an inner mock which has the same class methods as the facade.
After doing some research Javassist seemed to be the best tool for doing the bytecode manipulation. During the implementation of the desired bytecode modifier I struggled with some odd behavior of the application container but in the end I suceeded.
EjbMocker allows you to deploy a bytecode modified version of your EJB to be injected by Arquillian into your application server. You can completely control the behavior of the EJB with help of Mockito. Every method of the EJB is forwarded to an internal mocked instance with the same class signature.
An example project can be found at https://github.com/schakko/arquillian-warp-mocked-ejb. The EjbMocker contains usage instructions so I won’t repeat it here.