Chapter 9: Persistent Objects


Overview

Most programs have a common problem: they want to save part of their state, (i.e., part of their objects), in certain moments to make sure they survive the end of the program run. This process is called persisting. In another moment, and frequently in another program run, persistent objects should eventually be taken back from their exile to operative use.

There are many options to make data and objects "durable" in Java. Typical variants include:

  • Saving the object attributes to a file(e.g., in XML format).

  • Serialization of an object graph in a stream.

  • Saving the objects to a relational database (RDBMS)—with or without the use of a mapping tool. [1]

  • Using an object-oriented database (OODBMS).

A full discussion of the benefits and drawbacks of available persistence mechanisms goes beyond the scope of this book. These issues are covered in the literature [Barry96], which discusses in detail why and how an OODBMS can make our programming life easier. After all, we developers would like persistence to become a seamless part of object-oriented principles. In contrast, more than 10 years after the appearance of the first commercial object-oriented databases, most companies still favor their relational counterparts for software development, for good or bad reasons. In this chapter, we concentrate on the RDBMS variant and on Java database connectivity (JDBC) as a standardized programming interface to databases. The following problems occur when testing relational objects:

  • Accessing an external persistence medium takes much longer than accessing "normal" objects. This increases the runtime of a test suite (even with a small number of tests) beyond the limit we are willing to accept without grumbling. As a consequence, we take bigger steps in the test-driven development to cut down on test starts.

  • The consistency conditions of the data schema often require the existence of a very large number of supporting objects in order to be able to create our OUT in the database at all. The creation of these helper objects not only costs additional runtime, further slowing down the test suite, it can also turn into a maintenance nightmare, especially with complex schemas. For example, a new constraint in one place can mean that some of our tests fail during setup, or an additional relation in another place can mean that we have to create additional records to be able to get hold of a consistent instance of our CUT.

  • Before it actually starts, each test case has to ensure that both the number and state of all considered objects comply exactly with expectations. This means that no previous test case may leave garbage and that no other program (of another developer) interferes with the test.

  • Developers often have to use non-local databases for test purposes. This means that the underlying network generates additional runtime delays and increases the probability that problems unrelated to the test case itself cause it to fail.

Other persistence mechanisms can cause the same or similar troubles. These problems contribute to a situation where many developers who had initially been happy to work with the test-first approach throw in the towel when trying to integrate the persistence mechanism. This chapter explains how a combination of certain design principles and techniques can help to make unit testing for and with persistent objects less painful.

[1]A mapping tool maps objects to relational tables. One of the most popular tools of this kind is TopLink [URL:TopLink].




Unit Testing in Java. How Tests Drive the Code
Unit Testing in Java: How Tests Drive the Code (The Morgan Kaufmann Series in Software Engineering and Programming)
ISBN: 1558608680
EAN: 2147483647
Year: 2003
Pages: 144
Authors: Johannes Link

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net