Interaction between Persistence Layer and Client

As described in () and in (), it is normally not sufficient to test for the correct use of an interface through the client in one vein, and for correct implementation of an interface in another, at least from the theoretical perspective. In addition, we must closely examine the interplay of "neighboring" objects. For example, objects of the classes DailyReport and CRMDatabase are neighbors at runtime. However, if we were to test the complete interaction between report instances and database instances, then we would be back where we began in this chapter: endlessly long integration tests with a setup and tear-down complexity that would wear us out. For this reason, it makes sense to limit ourselves to a few interaction test cases to verify the basic interplay. More specifically, we would mainly do database read operations. To get the idea, look at the following code excerpt from the interaction test suite, which creates a real CRM database, populates it with some data, and hands it over to the DailyReport constructor:

public class CRMInteractionTest extends TestCase {
 private static CRMDatabase database;
 private static CustomerCategory category;
 private static Customer customer;
 private static Calendar today;
 private static void createScenario() throws CRMException {...
 today = Calendar.getInstance();
 database = new CRMDatabase(TEST_DB_URL);
 category = database.createCategory("fortune 100");
 customer = database.createCustomer("Customer 1", category);
 customer.addContact(today, "note 2");
 private static void deleteScenario() throws CRMException {...}
 public void testDailyReport() throws Exception {
 DailyReport report = new DailyReport(database, today);
 List contacts = report.allContactsForCategory(category);
 assertEquals(1, contacts.size());
 public static Test suite() {
 Test test = new junit.extensions.TestSetup(
 new TestSuite(CRMInteractionTest.class)) {
 protected void setUp() throws Exception {
 System.out.println("test setup: setUp()");
 protected void tearDown() throws Exception {
 System.out.println("test setup: tearDown()");
 return test;

This test class shows another option for how to accelerate certain tests. Our actual test suite is wrapped with a junit.extensions.TestSetup decorator in the suite() method. This decorator serves to accommodate those setup and tear-down operations needed only once for all tests of a suite. Because we want to limit our interaction tests to read operations in our specific case, we can build the testing scenario before the beginning of all interaction tests and tear down all test cases at once at the end. There is one more thing we should remember: when implementing the suite() method in test classes, we must be careful to really use this method in the aggregate test suite and not inadvertently in the default implementation:

public class AllTests {
 public static Test suite() {
 TestSuite suite = new TestSuite("All CRM tests");
 // instead of: suite.addTestSuite(CRMInteractionTest.class);
 return suite;