Persistent Dummy

Separating the persistence interface from the database connection puts us in a position to supply several implementations of that interface. One of them is a dummy implementation; we can use it in the tests for higher layers instead of a real database. The most important part of the dummy for our sample test looks like this:

public class DummyCRMPersistence implements CRMPersistence {
 private int id = 0;
 private Set customers = new HashSet();
 private Set categories = new HashSet();
 public CustomerCategory createCategory(String name)
 throws CRMException {
 CustomerCategory category = new CustomerCategory(name);
 return category;
 public Set allCategories() throws CRMException {
 return categories;
 public Customer createCustomer(String name,
 CustomerCategory category) throws CRMException {
 Customer customer = new Customer(name, category);
 return customer;
 public Set allCustomers(CustomerCategory category)
 throws CRMException {
 return customers;

All methods not shown here can remain empty for this test case. Note that the method allCustomers(...) returns all created customers and does not filter by category, in contrast to what the functionality actually requires. This complies with our principle to design dummy objects as simply as possible. It is sufficient for us to know that DailyReport instances use the allCustomers method to filter by categories. Naturally, the test should create only matching Customer objects:

public class DailyReportTest extends TestCase {
 private DailyReport report;
 private CRMPersistence persistence;
 private Calendar reportDate;
 private CustomerCategory catFortune100;
 protected void setUp() throws Exception {
 persistence = new DummyCRMPersistence();
 reportDate = Calendar.getInstance();
 report = new DailyReport(persistence, reportDate);
 catFortune100 = persistence.createCategory(
 "fortune 100");
public void testAllContacts() throws Exception {
 Customer customer1 = persistence.createCustomer(
 "Customer 1", catFortune100);
 Customer customer2 = persistence.createCustomer(
 "Customer 3", catFortune100);
 Calendar dayBefore = (Calendar) reportDate.clone();
 dayBefore.add(Calendar.DATE, -1);
 customer1.addContact(dayBefore, "note 1");
 customer1.addContact(reportDate, "note 2");
 customer2.addContact(dayBefore, "note 4");
 List contacts =
 assertEquals(1, contacts.size());
 // ...

The only remarkable addition to our modified test is that the constructor of DailyReport now additionally demands a CRMPersistence object. We already know this pattern from the introduction of dummy and mock objects. Most important, the test class is now shorter. Some of the database-specific code and the complete tearDown() method are no longer needed. The dummy class now allows us to test for correct behavior of our error handling mechanism. For this purpose, we configure the dummy object so that it throws the appropriate exception at the right moment (see Chapter 6, ). This way, we can simulate any error, from network failure to a violation of database constraints. An appropriate mock class would have been a good alternative to the DummyCRMPersistence class. But in view of the fact that it could have verified only the call of allCustomers(), we didn't think it would bring a benefit worth trying. This is certainly a question one can argue about.

If we want to expand a dummy database to the point that it becomes a lightweight database for testing purposes, we would generally have to put up with a larger development effort. The use of a lightweight or in-memory database (e.g., HsqlDB [URL:HsqlDb] and Cloudscape [URL:Cloudscape]) is more economical in most of these cases (see also , subsection Speeding Up the Test Suite).