A Test-Driven Development Stack for Java: Maven, Jetty, Mockito, and JAX-RS
A colleague of mine told me a story that exemplifies the common attitude of non-technical personnel toward unit testing. He had done a presentation on test-driven development (TDD) for a new team he joined. Afterwards, the project manager gathered all the other developers in a separate room and told them flat out: "We do not have time to write unit tests, so just disregard everything he said."
Unfortunately, all too often this is the short-sighted attitude that developers face. From my own experience, every project where unit testing was not a priority has usually ended in delays and missed deadlines. Worst of all, every single major change to the system (which is inevitable) would bring up the spectre of breaking some existing functionality. Sooner or later, this would blow up during manual testing and send the whole team into a chaotic frenzy of last-minute patches, which led to an even more unstable system down the road.
Implementing TDD from the Start
Many believe TDD is expensive, but that is true only if your system was designed without any regard for either unit testing or the system's long-term maintenance costs. On a recent project, my team took those two issues into account right from the beginning by ensuring that all of our functionality was easily testable and by choosing the right tools (Maven and Jetty) to facilitate TDD for server-side applications.
The end result was that we finished our feature set weeks ahead of schedule, and we were able to implement any change that came along later with confidence. Any code breakage showed up in our unit test runs very quickly. We fixed any new defects reported by QA by first adding a unit test to reproduce it and then fixing the actual problem we found. As such, our latest TDD development project was one of the least stressful I've ever experienced. But it was the result of making the right choices right at the very beginning. TDD is not just something you can easily bolt on to an existing project.
This article provides an overview of how my team integrated different open source Java tools (Maven, Jetty, Mockito, and JAX-RSwith Spring to tie them all together) into one coherent and productive TDD stack. As my experience in the previously described project illustrates, the combination can be incredibly productive.
Maven Support for Unit Tests and Integration Tests
Early on, my team decided to move away from Ant (our previous build system) and fully embrace Maven as our build and software management tool. Besides obvious benefits (such as library dependency management), we were delighted to also discover how easy it is to run unit and integration tests; you just need run "mvn test" or "mvn integration-test" at any point (and unit tests run automatically if you package your application).
We found it was easiest to split our test code via test suites: one for regular unit tests and one for integration. Then we could configure our Maven pom.xml to run the appropriate unit tests, as shown here:
plugin</artifactId> <configuration> <includes> <include>**/TestSuite.java</include> </includes> </configuration> <executions> <execution> <id>integration-tests</id> <phase>integration-test</phase> <goals> <goal>test</goal> </goals> <configuration> <skip>false</skip> <excludes> <exclude>none</exclude> </excludes> <includes> <include>**/IntegrationTestSuite.java</include> </includes> </configuration> </execution> </executions> </plugin>
Working with Maven in Eclipse
I've had very mixed experiences with the m2eclipse (i.e., the Maven for Eclipse) plugin. It seems great at first when it allows you to create new Maven projects or look for dependencies easily, but sooner or later it starts causing problems. Most often, my code stops compiling in Eclipse and starts showing errors (where there were none), but it will compile just fine if I run it via Maven from the command line.
In the end, I opted to just use regular Maven command-line functionality and invoke its Eclipse plugin (via "mvn eclipse:eclipse") to create and maintain the Eclipse project files. So, basically I use Eclipse for editing the code and Maven from command line to run it (if I ever change my pom.xml file).
If you want to debug your running code, this tutorial has instructions on how to set up Maven environment variables that will allow your Eclipse IDE to connect remotely to a running app.