Consider following trivial JavaEE application:
We want to test FooBean. However FooBean uses database or a distributed cache (e.g. Infinispan) or even another EJB bean. I.e. it depends on expensive component.
- units tests with mocking of expensive components;
- integration tests via FooService.
Option #1 is weak because mocking itself is tedious. Option #2 is weak because it could bring inadequate widening of FooService – all interesting methods of FooBean must get exposed somehow as JAX-RS resources.
Another approach is too use Arquillian for testing. It combines options #1 and #2 but is free of their weaknesses. Here is its main idea:
Below is an example of a test Arquillian class and resulting test artifact (EAR test-foo-ejb.ear in our case):
- tested FooBean (along with its interface Foo) lives inside of foo-ejb.jar, the latter is included into test artifact as is;
- FooTest class is included into test-foo-ejb.war and is included into test artifact as well.
Running mvn verify or mvn test (depending on whether this test is of unit or integration type) will result in:
- crafted test artifact is deployed to container;
- since this is a real container than all necessary dependencies of a component (e.g. database) are satisfied in a natural way without any mocking or simulation;
- code inside of test class is launched by Arquillian. Code is executed inside a container with full access to a tested component!
- after test is executed test artifact is undeployed from container.
Thanks to modules isolation inside of an application container coexistence of the same FooBean inside two different EARs (real-foo.ear and crafted test-foo-ejb.ear) is possible. The same time all relevant dependencies (e.g. on database) are retained and this gives an ability to touch and call FooBean in any way we want from FooTest.