JBoss.orgCommunity Documentation
When you use a unit testing framework like JUnit or TestNG, your test case lives in a world on its own. That makes integration testing pretty difficult because it means the environment in which the business logic executes must be self-contained within the scope of the test case (whether at the suite, class or method level). The bonus of setting up this environment in the test falls on the developer's shoulders.
With Arquillian, you no longer have to worry about setting up the execution environment because that is all handled for you. The test will either be running in a container or a local CDI environment. But you still need some way to hook your test into this environment.
A key part of in-container integration testing is getting access the container-managed components that you plan to test. Using the Java new operator to instantiate the business class is not suitable in this testing scenario because it leaves out the declaratives services that get applied to the component at runtime. We want the real deal. Arquillian uses test enrichment to give us access to the real deal. The visible result of test enrichment is injection of container resources and beans directly into the test class.
Before Arquillian negotiates the execution of the test, it enriches the test class by satisfying injection points specified declaratively using annotations. 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
- CDI 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.
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("test.jar", JavaArchive.class)
.addClass(NameOfClassUnderTest.class)
.addManifestResource(new ByteArrayAsset(new byte[0]), 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.
When running your tests the embedded Weld EE container, Arquillian activates scopes as follows:
Application scope - Active for all methods in a test class
Session scope - Active for all methods in a test class
Request scope - Active for a single test method
Scope control is experimental at this point and may be altered in a future release of Arquillian.