@RunWith(Arquillian.class) public class GreeterTestCase { @Inject private Greeter greeter; ... }
Before Arquillian negotiates the execution of the test, it enriches the test class by satisfying injection points specified declaratively using annotations.
Injection points are recognized in the following two locations:
Field (any visibility)
@Test method argument
Here's an example of a field injection in a test class:
@RunWith(Arquillian.class) public class GreeterTestCase { @Inject private Greeter greeter; ... }
Here's an example of a method argument injection in a test method:
@Test public void testGreeting(Greeter greeter) { ... }
Note that the @Inject annotation is not required when injecting into a method argument.
There are three injection-based enrichers provided by Arquillian out of the box:
@Resource - Java EE resource injections
@EJB - EJB session bean reference injections
@Inject, @Resource, @EJB, @PersistenceContext and @PersistenceUnit - CDI-supported injections
The first two enrichers use JNDI to lookup the instance to inject. The CDI injections are handled by treating the test class as a bean capable of receiving standard CDI injections (non-contextual injection). Since CDI requires containers to satisfy all Java EE injection points on a CDI bean, the @Resource, @EJB, @PersistenceContext and @PersistenceUnit injections are supported transitively by the CDI enricher. In fact, because of CDI's tight integration with the container, @EJB injections in the test class are satisfied according to specification when the CDI enricher is available.
The @Resource annotation gives you access to any object which is available via JNDI. It follows the standard rules for @Resource (as defined in the Section 2.3 of the Common Annotations for the Java Platform specification).
The @EJB annotation performs a JNDI lookup for the EJB session bean reference using the following equation in the specified order:
"java:global/test.ear/test/" + fieldType.getSimpleName() + "Bean", "java:global/test.ear/test/" + fieldType.getSimpleName(), "java:global/test/" + fieldType.getSimpleName(), "java:global/test/" + fieldType.getSimpleName() + "Bean", "java:global/test/" + fieldType.getSimpleName() + "/no-interface", "test/" + unqualified interface name + "Bean/local", "test/" + unqualified interface name + "Bean/remote", "test/" + unqualified interface name + "/no-interface", unqualified interface name + "Bean/local", unqualified interface name + "Bean/remote", unqualified interface name + "/no-interface"
If no matching beans were found in those locations the injection will fail.
At the moment, the lookup for an EJB session reference relies on some common naming convention of EJB beans. In the future the lookup will rely on the standard JNDI naming conventions established in Java EE 6.
In order for CDI injections to work, the test archive defined with ShrinkWrap must be a bean archive. That means adding beans.xml to the META-INF directory. Here's a @Deployment method that shows one way to add a beans.xml to the archive:
@Deployment public static JavaArchive createTestArchive() { return ShrinkWrap.create(JavaArchive.class, "test.jar") .addClass(NameOfClassUnderTest.class) .addAsManifestResource(EmptyAsset.INSTANCE, Paths.create("beans.xml"))
In an application that takes full advantage of CDI, you can likely get by only using injections defined with the @Inject annotation. Regardless, the other two types of injection come in handy from time-to-time.