JBoss.orgCommunity Documentation
We believe that integration testing should be no more complex than writing a basic unit test. We created Arquillian to realize that goal. One of the major complaints we've heard about Seam 2 testing (i.e., SeamTest) was, not that it isn't possible, but that it isn't flexible and it's difficult to setup. We wanted to correct those shortcomings with Arquillian.
Testing needs vary greatly, which is why it's so vital that, with Arquillian (and ShrinkWrap), we have decomposed the problem into its essential elements. The result is a completely flexible and portable integration testing framework.
Arquillian is the missing link in Java EE development. Developers have long had to fend for themselves in the testing stage, burdened with bootstrapping the infrastructure on which the test depends. That's time lost, and it places a high barrier to entry on integration testing. Arquillian tears down that barrier.
Arquillian is a container-oriented test framework. It picks up where unit tests leave off, targeting the integration of application code inside a real runtime environment. Just as Java EE 5 simplified the server programming model by providing declarative services for POJOs, Arquillian equips tests with container lifecycle management and enrichment.
With Arquillian, you write a basic test case and annotate it with declarative behavior that says, "run with Arquillian." Launching the test is as simple as right-clicking the test class in the IDE and selecting Run As > JUnit or TestNG test. Based on the classpath configuration, Arquillian starts or binds to the target container (JBoss AS, GlassFish, OpenEJB, etc) and deploys the test case bundled with the test archive defined in the @Deployment method. Your test executes inside the container and enjoys all the same services as an application component. That means you get dependency and resource injection into the test, you can access EJBs, you can load a persistence unit, you can get a handle to a database connection, etc. Yet, on the surface, it looks like any other unit test. (Arquillian also has a client execution mode, which only deploys the test archive, not the test case).
Instead of bringing your runtime to the test, Arquillian brings your test to the runtime.
Features of Arquillian include:
Runnable from both JUnit and TestNG
Abstracts out server lifecycle and deployment
Injects resources like managed beans, EJBs or objects from JNDI into the test instance
Zero reliance upon a formal build; can be run or debugged from IDEs like Eclipse, IDEA, NetBeans
Supports remote and embedded containers: JBoss AS, GlassFish, Jetty, Tomcat, OpenEJB, OSGi and more on the way
Enables pass-by-reference between the test and the server, even if the server is in another JVM from the test launcher
Provides an extensible SPI - plug in your own containers and take advantage of the Arquillian bus to provide services to the test
No longer does writing a test involve system administration tasks. No more custom scripts or copy-paste Maven configuration. No more full builds. No more test classpath mayhem. No more looking up resources manually in JNDI. No more reliance on coarse-grained, black-box testing.
Arquillian keeps you focused on the test, while enjoying the services provided by the container. And it's turning heads.
Arquillian combines a unit testing framework (JUnit or TestNG), ShrinkWrap, and one or more supported target containers (Java EE container, servlet container, Java SE CDI environment, etc) to provide a simple, flexible and pluggable integration testing environment.
At the core, Arquillian provides a custom test runner for JUnit and TestNG that turns control of the test execution lifecycle from the unit testing framework to Arquillian. From there, Arquillian can delegate to service providers to setup the environment to execute the tests inside or against the container. An Arquillian test case looks just like a regular JUnit or TestNG test case with two declarative enhancements, which will be covered later.
Since Arquillian works by replacing the test runner, Arquillian tests can be executed using existing test IDE, Ant and Maven test plugins without any special configuration. Test results are reported just like you would expect. That's what we mean when we say using Arquillian is no more complicated than basic unit testing.
At this point, it's appropriate to pause and define the three aspects of an Arquillian test case. This terminology will help you better understand the explainations of how Arquillian works.
container — a runtime environment for a deployment
deployment — the process of dispatching an artifact to a container to make it operational
archive — a packaged assembly of code, configuration and resources
The test case is dispatched to the container's environment through coordination with ShrinkWrap, which is used to declaratively define a custom Java EE archive that encapsulates the test class and its dependent resources. Arquillian packages the ShrinkWrap-defined archive at runtime and deploys it to the target container. It then negotiates the execution of the test methods and captures the test results using remote communication with the server. Finally, Arquillian undeploys the test archive. We'll go into more detail about how Arquillian works in a later chapter.
So what is the target container? Some proprietary testing container that emulates the behavior of the technology (Java EE)? Nope, it's pluggable. It can be your actual target runtime, such as JBoss AS, GlassFish or Tomcat. It can even been an embedded container such as JBoss Embedded AS, GlassFish Embedded or Weld SE. All of this is made possible by a RPC-style (or local, if applicable) communication between the test runner and the environment, negotiating which tests are run, the execution, and communicating back the results. This means two things for the developer:
You develop Arquillian tests just like you would a regular unit test and
the container in which you run the tests can be easily swapped, or you can use each one.
With that in mind, let's consider where we are today with integration testing in Java EE and why an easy solution is needed.
Integration testing is very important in Java EE. The reason is two-fold:
Business components often interact with resources or sub-system provided by the container
Many declarative services get applied to the business component at runtime
The first reason is inherent in enterprise applications. For the application to perform any sort of meaningful work, it has to pull the strings on other components, resources (e.g., a database) or systems (e.g., a web service). Having to write any sort of test that requires an enterprise resource (database connection, entity manager, transaction, injection, etc) is a non-starter because the developer has no idea what to even use. Clearly there is a need for a simple solution, and Arquillian fills that void.
Some might argue that, as of Java EE 5, the business logic performed by most Java EE components can now be tested outside of the container because they are POJOs. But let's not forget that in order to isolate the business logic in Java EE components from infrastructure services (transactions, security, etc), many of those services were pushed into declarative programming constructs. At some point you want to make sure that the infrastructure services are applied correctly and that the business logic functions properly within that context, justifying the second reason that integration testing is important in Java EE.
The reality is that you aren't really testing your component until you test it in situ. It's all to easy to create a test that puts on a good show but doesn't provide any real guarantee that the code under test functions properly in a production environment. The show typically involves mock components and/or bootstrapped environments that cater to the test. Such "unit tests" can't verify that the declarative services kick in as they should. While unit tests certainly have value in quickly testing algorithms and business calculations within methods, there still need to be tests that exercise the component as a complete service.
Rather than instantiating component classes in the test using Java's new operator, which is customary in a unit test, Arquillian allows you to inject the container-managed instance of the component directly into your test class (or you can look it up in JNDI) so that you are testing the actual component, just as it runs inside the application.
Do you really need to run the test in a real container when a Java SE CDI environment would do?
It's true, some tests can work without a full container. For instance, you can run certain tests in a Java SE CDI environment with Arquillian. Let's call these "standalone" tests, whereas tests which do require a full container are called "integration" tests. Every standalone test can also be run as an integration test, but not the other way around. While the standalone tests don't need a full container, it's also important to run them as integration tests as a final check just to make sure that there is nothing they conflict with (or have side effects) when run in a real container.
It might be a good strategy to make as many tests work in standalone mode as possible to ensure a quick test run, but ultimately you should consider running all of your tests in the target container. As a result, you'll likely enjoy a more robust code base.
We've established that integration testing is important, but how can integration testing being accomplished without involving every class in the application? That's the benefit that ShrinkWrap brings to Arquillian.
One huge advantage ShrinkWrap brings to Arquillian is classpath control. The classpath of a test run has traditionally been a kitchen sink of all production classes and resources with the test classes and resources layered on top. This can make the test run indeterministic, or it can just be hard to isolate test resources from the main resources.
Arquillian uses ShrinkWrap to create "micro deployments" for each test, giving you fine-grained control over what you are testing and what resources are available at the time the test is executed. An archive can include classes, resources and libraries. This not only frees you from the classpath hell that typically haunts test runners (Eclipse, Maven), it also gives you the option to focus on the interaction between an subset of production classes, or to easily swap in alternative classes. Within that grouping you get the self-assembly of services provided by Java EE—the very integration which is being tested.
Let's move on and consider some typical usage scenarios for Arquillian.
With the strategy defined above, where the test case is executed in the container, you should get the sense of the freedom you have to test a broad range of situations that may have seemed unattainable when you only had the primitive unit testing environment. In fact, anything you can do in an application you can now do in your test class.
A fairly common scenario is testing an EJB session bean. As you are inside the container, you can simply do a
JNDI lookup to get the EJB reference and your test becomes a client of the EJB. But having to use JNDI to get
a reference to the EJB is inconvenient (at least to Java EE 5 developers that have become accustomed to
annotation-based dependency injection). Arquillian allows you to use the @EJB
annotation to
inject the reference to an EJB session bean into your test class.
EJB session beans are one type of Java EE resource you may want to access. But that's just the beginning.
You can access any resource available in a Java EE container, from a UserTransaction
to
a DataSource
to a mail session. Any of these resources can be injected directly into
your test class using the Java EE 5 @Resource
annotation.
Resource injections are convenient, but they are so Java EE 5. In Java EE 6, when you
think dependency injection, you think JSR-299: CDI. Your test class can access any bean in the
ShrinkWrap-defined archive, provided the archive contains a beans.xml file to make it a bean archive. And you
can inject bean instances directly into your class using the @Inject
annotation, or you can
inject an Instance
reference to the bean, allowing you to create a bean instance when needed
in the test. Of course, you can do anything else you can do with CDI within your test as well.
Another important scenario in integration testing is performing data access. If the ShrinkWrap-defined archive
contains a persistence.xml descriptor, the persistence unit will be started when the archive is deployed
and you can perform persistence operations. You can obtain a reference to an EntityManager
by injecting it into your class with @PersistenceContext
or from a CDI producer-field.
Alternatively, you can execute the persistence operation indirectly through an EJB session bean or a managed bean.
Those examples should give you an idea of some of the tasks that are possible from within an Arquillian-enhanced test case. Now that you have plenty of motivation for using Arquillian, let's look at how to get started using Arquillian.