JBoss.orgCommunity Documentation

Chapter 5. Test enrichment

5.1. Injection into the test case
5.2. Active scopes

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:

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.

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:

Scope control is experimental at this point and may be altered in a future release of Arquillian.