Go forth and test in-container!
Arquillian: A Component Model for Integration Testing - Part 4
When it's all said and done, Arquillian shares the result of the test method with the original test runner and the rest of the lifecycle plays out just like with a unit test, where the results are reported to the command line, file or IDE plugin window.
As the test runner is wrapping things up, Arquillian will shut down the container if necessary. Again, the JUnit test plugin has no idea any remote communication or container lifecycle management is occurring. You can even mix Arquillian tests and plain unit tests in the same test suite. Arquillian's minimal footprint is really the beauty of it.
Running the Arquillian Test
Notice that despite talking a lot about incontainer testing using Arquillian, we haven't mentioned which container we are using to test. That's because it's a runtime decision.
Arquillian tests can be executed in any container that is compatible with the component model used in the test (that is, as long as the container has an Arquillian adaptor). The example above can be executed in any container that provides the EJB component model. You could run the test in an embedded EJB container for fast execution or easy debugging. You could also execute it in a full Java EE 6 container, perhaps to verify it works in the same container that you run your production code. Basically, your test is a free agent ;)
How do you select a container? Having code in hand, you're likely itching to see it work. There are only three steps involved:
- Add the Arquillian container adapter for the target container to the test classpath.
- Add the container runtime (for an embedded container) or client (for a managed or remote container) to the test classpath.
- Execute the test as usual, using a JUnit (or TestNG) plugin (Eclipse, IntelliJ, NetBeans, Ant, Maven, etc).
Arquillian selects the container to target based on what is available on the classpath. That's the secret sauce. Arquillian requires no other configuration (though you can configure certain elements of the target container using the arquillian.xml descriptor). In Maven, the classpath is controlled using profiles. One profile is setup for each container we are targeting. Listing ALL-9 shows the profile for OpenEJB 3.1 embedded, the standalone EJB 3.0+container developed by Apache. Now we'll run the tests in OpenEJB embedded by activating this profile using the command in Listing ALL-10.
Here's the really powerful part. We can run the exact same test on any container that supports EJB 3.0, such as JBoss AS 5 and above. Let's assume there's a Maven profile named arq-jbossas-managed defined in the pom.xml that includes the JBoss AS server manager library and corresponding Arquillian container adapter library. We can then run our test on JBoss AS by activating this profile when we run the Maven test goal:
Consult the Arquillian reference guide to learn more about integrating an Arquillian test suite into your build or IDE. In truth, though, there's not much to it.
Now that you've got one Arquillian test under your belt, let's take a quick tour of what else it can be used to test.
Where We're Going, We Don't Need EJB
All this talk about EJB may have left you with the impression that Arquillian is just for EJB testing. That's certainly not the case. Neither Arquillian nor ShrinkWrap are tied to Java EE. Not its containers, archives or component model.
EJB is just one of the component models already supported. Similar integration can be offered for any container and (at the moment, Java) programming model, simplifying integration tests to three annotations (or more) and some ShrinkWrap packaging.
The Java EE 5 and Java EE 6 stacks (EJB, JPA, JTA, CDI, JMS, JAX-RS, JSF, Servlet, etc) are already well supported. Other component models supported include JSR-299 (CDI) standalone, OSGi and JSR-322 (JCA) standalone. Additional integrations are under development, such as JPA (standalone), Hibernate, Spring and JBoss MC . Suppor t for other JVM languages could open the door for Arquillian to drive integration tests beyond Java, such as Ruby on Rails. Arquillian is already being used to black box test JRuby-based TorqueBox applications using the client execution mode.
All of this is possible because Arquillian didn't start out by trying to address a narrow problem. Instead of focusing on building a test infrastructure for a specific programming model like Servlets or EJBs, Arquillian focuses on providing a component model for your tests through an extensible set of SPIs.
Arquillian is extensible in nearly every way, so adding a new container and / or programming model is just a matter of implementing a handful of Arquillian SPIs. Figure ALL-3 shows how the SPI implementations fit into the Arquillian stack.
There's nothing stopping you from rewriting one of the existing SPI implementations or container adapters if you want to change the behavior, though we encourage you to join the community and contribute your improvements for everyone's benefit.
One of the ways Arquillian manages complexity as you move to higher level tests is to treat auxiliary testing frameworks, such as JSFUnit for testing JSF pages, as an extension of the tests' component model.
Do you know what you have to do to integrate JSFUnit into your test suite? With Arquillian, it's just a matter of adding a single JAR file to the classpath, arquillian-framework-jsfunit.jar. JSFUnit becomes part of the component model for your test. Expect similar transparent integrations with tools such as DBUnit, Selenium, HTTPUnit and so on. Arquillian will continue to surprise us because it's truly an open test automation platform.
Learn before You Test
In learning that Arquillian is a testing framework, you may be inclined to write it off as something that's only useful when you are ready to lay down tests for your application. In doing so, you overlook one of the most powerful and effective uses of Arquillian; as a learning tool.
It's a common misconception that a developer can just start out on day one writing application code or even tests, especially when learning a new programming model, container or domain model.
Consider a building contractor who just purchased a new saw. Do you think he is going to head straight to the job site and start cutting material that costs $5/ft? Not likely. He's first going to take the saw to his work bench and practice on scrap wood to get a feel for how it cuts. He'll try it one way then another and so on until the saw becomes a natural extension of his hands. Only then is he going to head to the job site and start making "production" cuts. It's the same way with the application you are going to work on. You want to figure things out before you start laying down production code.
Let's say I'm teaching you a new programming model, perhaps EJB or CDI. The components you create get placed into a runtime and invoked as backend services. By themselves, they are not executable. So how can you see if they work? One solution is using some sort of user interface (UI) that can invoke the component. In a Java EE application, the UI is typically a web page rendered by a Servlet.
How many times have you created a web page with a button and a few inputs just to experiment with a backend service? And I bet you had to do more than just create the web page. You likely had to assemble a script to package the WAR and manually deploy it to the container. That's a heck of a lot of work just to stand up a component. Now don't forget to delete that web page so it doesn't leave a back door open into your application!
Wouldn't it be nice if you could invoke the component directly without having to do all that busy work? That's precisely the infrastructure Arquillian provides for you. Perhaps you now appreciate that Arquillian's utility goes well beyond writing tests. It's an opportunity to explore the target platform and get comfortable writing code for that environment. It's about figuring stuff out. It's a framework for creating a "Hello world" at each step along your learning path. Combine that with the debugging capabilities of your IDE, which you can leverage since Arquillian tests can be launched from the test plugin in your IDE, and you can master a programming model in no time.
You can even try the same code on multiple containers to make sure that you aren't relying on non-compliant (or buggy) behavior of a single container. Don't stop there. Use Arquillian to create prototypes to share with the customer during the design phase. Nowhere does it say demos must be user interfaces. Your business logic may be performing calculations (such as our mortgage calculator), parsing text, reading and writing to the database and so forth. You can use Arquillian to show this functionality is working, for real. Arquillian even has Spock integration, so you can embrace the Behavior Driven Design (BDD) methodology.
My advice to you (as well as technical authors): use Arquillian as a learning device. You can keep those tests around or you can throw them away. Either way, the experience you gain from experimenting with Arquillian is timeless.
Integration Testing as it Should Be
Build free and in-container. That's the way integration testing should be and it's what makes Arquillian's approach so different. Arquillian can make the transition from unit to integration smooth, without losing the ability to leverage the IDE and debugger, because:
• The setup is minimal.
• There is no base class to extend.
• You can leverage the native features of the testing framework.
• You run or debug the test just like a regular unit test.
• You have control over which classes go in the deployment.
• The test has access to the component model of the application.
• The test is portable to any container that provides the component model in use.
If you choose to adopt Arquillian now, there's no doubt it will continue to grow to match your testing requirements. With its extensible SPIs, there's no telling all the ways Arquillian may help enrich your test suite.
Go forth and test in-container!
Interested to learn more? Be sure to check out the follow-up article appearing in the April issue of NFJS, The Magazine. The article will describe how to design your tests so they run in multiple containers, then showcases numerous scenarios and technologies that Arquillian enables you to test with ease. By the end, you'll be ready to test everything from managed beans to web pages.
You can also join me at JAX London to learn about the future of Java enterprise testing using Arquillian.