When to avoid the Container during Unit Testing
Over the course of my career, I have been eagerly reading, interviewing colleagues and experimenting with my own unit testing methodologies. It was only recently, that a fellow odecee colleague and I sat in a room and attempted to map out what we thought was a practical and repeatable unit testing methodology that we could take to other projects and cement a position on a unit testing pattern for odecee.
After brainstorming our ideas and categorising all the types of development testing, we were able to define a taxonomy that represented all types of tests that a development team should be creating. After some further refinement, I described the process in an odecee white paper with view to lay the foundations for odecee’s unit testing methodology.
Central to our discussions was the topic of this blog; when should a developer avoid testing in the container? To better illustrate the question, it’s best if I define what container avoidance is. First and foremost, all JEE applications will have a target deployment environment which typically includes an installation of some JEE container (WebSphere Application Server, Tomcat etc.) where the application that is being developed will be deployed to. Now, all containers provide foundation services to which the application can call upon to access some resource; albeit a database, LDAP directory, Connector, JMS provider, even the humble HTTPRequest object. The application under development will typically have a dependency on one or more resources managed by the container and will therefore need the services during the execution of the application. If you want to run your unit tests on an application that has a target container which is managing resources, then testing your application outside your container will require a strategy to provide replacements for your container managed services. The process in which a solution is derived that substitutes a container service for a fake one, albeit a stub or mock, is what I call container avoidance.
One implementation of a container avoidance strategy is to use an off-the-shelf framework like Spring, where each class in your application is configured as an “bean” and defined to have dependencies to other “beans”. Loosely coupling your java classes in this manner puts you in an ideal situation to abstract all your (potentially) container service providers. Now, swapping out your providers should be a simple configuration task; a task that can be abstracted by your unit testing framework, like the AbstractTransactionalDataSourceSpringContextTests. Seemingly simple really, but does require some planning and commitment to the testing pattern.
Once all your providers are abstracted, we have achieved Container Avoidance and can now run our primary test objects outside the container and weave our test code.
So, now that we have a method to avoid most container services, we’ve managed to reach further into our classes using our unit test code than ever before. Has this process increased the likelihood of a “works-first-time” deploy? No, it certainly has not. In the view to implement container avoidance, we’ve missed testing other aspects of the system under test, like Deployment Descriptors, System Configurations, View Concerns and many more things that make up the working application.
Although we have definitely achieved a engineering feat, l would characterise container avoidance as an academic task; one which can easily miss the pragmatic viewpoint of unit testing: proving the business function.
Well, where too from here? How far should we go with abstracting our providers? Only datasources? Only EJB’s? What about Web Services? It’s a tough question. And the answer depends on your philosophy of unit testing. Complex systems have many moving parts, orchastrated in a perfect harmony that will reliably deliver business value time and time again. Therefore, we should try our hardest to test the business functions and not the finest code granularity in a view to attain high levels of code coverage. This means using the container services by deploying your application and testing all facets of the system, including container configuration, in the test cycle. Lets not forget, if it was not for the services of the container, we would be forced to write multi-threaded applications on every customer engagement. Now that would surely be another engineering feat.
- oscar.huseyin's blog
- Login or register to post comments
- 1079 reads
- Flag as offensive
- Email this Blog entry
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)







Comments
Fred Grott replied on Wed, 2008/01/30 - 9:06am
Steven Devijver replied on Wed, 2008/01/30 - 10:29am
Every application is different, and one testing strategy may be a better fit than an other.
We test in the container a lot and it has helped us to increase the quality of our software dramatically, something that we could not achieve before when we focused on unit testing. Running tests takes a lot of time, we gladly accept that and have found ways to work around that problem.