Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Pattern your way to automated regression testing

Implement popular design patterns to overcome unit-testing hurdles

  • Print
  • Feedback
We have all heard the mantra: test, test, test. Unit test all mission-critical business logic. If possible, write the unit tests before you write the code. Test everything you can, and test it often.

Frequent testing is one of the extreme programming fundamentals, a set of practices growing in popularity because it provides a sound approach to dealing with the inevitable complexity and change of today's programming projects. But the simple mantra to test is much easier said than done, and far more often preached than practiced. Deadlines approach, managers loom, and important testing gets postponed yet again.

In the past, a major obstacle to adequate unit testing was the inherent startup costs to design and implement an acceptable unit-testing framework. Without a framework, unit tests were haphazardly implemented, and very difficult to aggregate into test suites that ran with the click of a button. Fortunately, Erich Gamma and Kent Beck have implemented Beck's Smalltalk unit testing framework in Java, called JUnit. This excellent framework, already the de facto standard for implementing unit testing in Java, provides the basic plumbing for developers to quickly generate whole test suites that validate their programs with the click of a button. With JUnit, a major excuse for eschewing unit tests has been obviated.

"Trade"-offs

However, there is a more pernicious obstacle to unit testing system parts that involve access to a database system. As an example, imagine a system that processes trade transactions in a stock market simulator. One or more external systems place trade orders into a database, which our simulator then reads and processes. Assume our goal is to implement this system as well as all the unit tests necessary to ensure its smooth run. You can easily test certain system parts with JUnit.

Now consider the object that calculates the transaction's dollar value. The test could simply create a Trade object with the desired arguments, and then assert that the getPrice() method returns the expected amount. But what about the TradeProcessor object, which reads and processes the incoming database requests? Suppose myriad combinations of incoming trade orders have different outcomes in our simulator, and we wish to test those various combinations as part of our JUnit suite. Could you unit test that part of the system? (If you're not convinced you can by the end of this article, I haven't done my job!)

We could approach unit testing this core logic in several ways. We could set up multiple test databases (one for each test case), and between each unit test, change the database the program queries. We would have to ensure that those databases are immutable, since we want subsequent runs to produce identical results. If the system's nature is such that merely running a test causes the database to produce different results (for example, by setting the status of "pending" trades to "processed"), this approach is very problematic indeed. What's more, you would then have to somehow keep all those databases, with their precise state necessary for successful unit tests, stored with that source code version. For most source code revision-control tools, this requirement would present a major problem.

  • Print
  • Feedback

Resources