Software Testing With Spring Framework
By: Srini and Kavitha Penchikala
Testing is an integral part of enterprise software development. It is as important, if not the most important, as any other phase of the Software Development Lifecycle (SDLC). But testing an enterprise application is easier said than done. There are several constraints that make testing effort in a project a major challenge. These constraints usually fall into two categories: framework related constraints and project methodology related constraints.
An example of framework related constraints is that J2EE architecture model does not take into account the aspect of unit testing as part of the software development. Since the container (application server) is the core component of J2EE run-time architecture, it is difficult to test applications built based on J2EE API, outside the container. Unit testing (outside the container) is essential to achieve high test coverage. It's also easy to reproduce many failure scenarios without the overhead of application server setup and code deployment. It is vital to ensure that tests can be run quickly which is important in development or production support phases of the project. The task of verifying code using unit testing minimizes unproductive time spent waiting for the application to be deployed every time we make a code change.
Since the code in a traditional J2EE application depends heavily on the application server, its functionality can be fully tested only when deployed inside a J2EE container. But in-container testing is too slow and too much of an obstacle to developer productivity especially if the project is relatively large and number of code artifacts (java source files) is high.
There are some J2EE frameworks that are built from ground-up to provide excellent support for integrating software testing into the development process. Spring is one of such java enterprise application development frameworks.
Recently, I did some consulting on an enterprise java application my wife worked on for a local Tier-One automotive supplier company. The project was to create a Customer Profile Management System used to track the profiles of their customer companies. The architecture of this application included Hibernate 3.0, Spring 2.0, and JBoss 4.0 technologies. The project team followed an Agile software development approach to deliver the requirements in one-week iterations. They used the integration testing features offered by Spring framework, to test the application code in Data Access and Service layers. We really liked the testing support provided by Spring framework. It simplified testing to a great extent and made the aggressive one-week development iterations possible and manageable.
This article provides an overview of the support provided by Spring framework in the areas of unit and integration testing. I will use a sample loan processing web application to help the readers in implementing an Agile Testing framework in a typical Java EE application and how to use Spring test classes to test the application functionality.
Agile Software Testing
A software development project must include good design and architecture practices as well as good testing practices. An application may have a very good architecture, design and code, but if it's not well tested, it cannot be considered a successful product. Some companies (software service vendors) live and die by the quality of their products and testing is crucial in the success of these companies.
Agile software development requires a comprehensive testing strategy in order to achieve the agility and quality in the software development project. Agile testing includes unit testing as well as integration testing. This means that we should be able to execute the tests as quickly as possible (one way to achieve the agility is to run the tests outside the application server). Test Driven Development (TDD) is one of the key elements of Agile development process. Spring and other light-weight containers such as PicoContainer and HiveMind provide great support for test driven software development.
Let's briefly look at the significance of unit and integration testing in a typical Java EE development project and objectives and constraints of each testing approach.
Unit testing is used to test a specific unit (class) in the application. Unit tests should be written to test all the methods in the class including all exception paths in the methods. The objective of unit testing is to be able to quickly test any new code or changes to existing code without the overhead and additional time involved in tasks such as server configuration, services setup and application deployment. Developer unit testing is critical since it is easier and cheaper to find and fix bugs earlier in software development lifecycle (at coding and unit testing phases) rather than in the later stages.
JUnit is the popular testing framework used for writing unit tests. In JUnit tests, we simply instantiate the objects using new operator, without having to worry about the container's JNDI resources and J2EE services such as resource pooling, JDBC connection pools and JMS queues. We can also use testing techniques like Mock Objects to test the code in isolation. With unit testing, there is no need for any infrastructure setup for an application server or even a database server.
There are some limitations to unit testing. Unit tests don't address the testing of functional requirements of the application. These tests only cover testing of each module in the application. Also, we can't test scenarios like asynchronous services which require JMS message queues configured inside the application server. But we should still be able to unit test as much application functionality as possible and use the in-container tests for only those functions that cannot be tested outside the container.
Unit tests are very useful to test a module or class in isolation. But it's also important to do integration testing of the application to see how various modules would work together when assembled in the integrated environment. Some functions that work fine at module level may not work correctly when integrated with other modules in the application. This scenario is very realistic in an agile development environment where different developers work on different parts of the application at the same time and they need to merge code changes on a regular (in some development teams daily) basis. The integration tests include testing round-trip calls between client and service layers of the application. Most of the integration tests usually run in the container. But to be truly agile, we will need to run atleast some integration tests without any code deployment to the container.
Integration tests are useful in DAO layer where the implementations of DAO interfaces cannot be unit tested effectively. Other objectives of integration testing is to test aspects such as remote service, state (session) management, web flow and transaction management. Integration testing has some constraints as well. It takes longer time to run these tests. Since the application needs to be deployed inside Java EE container, there is also the server setup and configuration overhead involved in running these tests.
It should be noted that integration testing is complimentary testing, not a substitute for unit testing. Developers should first write sufficient unit tests for each java class in the application to achieve a good code coverage. At the same time, there should be enough integration tests written to cover different use case scenarios in the application that can not be tested with unit tests.
There are several other types of testing in addition to unit and integration tests. Following table lists different testing strategies and their objectives.
... to read more articles, visit http://sqa.fyicenter.com/art/