Case Study

Pre-populating the Database

Previous Next
For many tests of persistence, the database must be put in a particular state before the test can be run. For instance, tests of finder methods require some number of data values to already exist, from which the correct subset must be selected. Tests of CRUD operations also require pre-existing values. Few objects exist without relationships to other objects. These objects on which the subject of the test depends need to be created before the main body of the test executes. Here we show how this problem is addressed in the Case Study. The method onSetUpInTransactionAtBeginning of AbstractDaoTest reads in dependencies and prepopulated objects into local variables, and then calls methods (populateDependencies and prepopulate) that persist those values. First, notice how objects are prepopulated. In the Case Study, "prepopulated" means that objects of the type persisted by the DAO under test are inserted in the database before the method under test is exercised. AbstractDaoTest is a generic class; objects of type V are Persistable, which is merely a layer supertype for all domain model objects that bestows an identifier property; objects of type D are DAO classes that extend the Case Study's AbstractDao class, which persists objects of generic type V. Given this, we can understand that the prepopulate method works by taking all of the prepopulated objects read from the SpringUnit context and calling the create method of the DAO of type D that is the subject of the test. AbstractDaoTest.java (excerpt)
public abstract class AbstractDaoTest<V extends Persistable, D extends AbstractDao<V>> extends SpringUnitTransactionalTest {

	<-- Note that onSetUpInTransactionAtBeginning is deprecated in SpringUnit 0.6 -->
	protected void onSetUpInTransaction() throws Exception {
		this.subject = (D)getObject("subject");
		this.dependencies = getObject("dependencies");
		populateDependencies();
		this.prepopulated = (List<? extends V>)getObject("prepopulated");
		prepopulate();
	}

	protected void prepopulate() throws Exception {
		if (getPrepopulated() != null && getPrepopulated().size() > 0) {
			getSubject().create(getPrepopulated());
		}
	}

	protected List<? extends V> getPrepopulated() {
		return this.prepopulated;
	}
	
	protected D getSubject() {
		return this.subject;
	}
	
	private List<? extends V> prepopulated;
	private D subject;
	
	protected void populateDependencies() throws Exception {
	}

	/* other methods and fields omitted */
	
}
The means of prepopulating the database is common across all types, but the means of creating object dependencies is type-specific. For this reason, the method populateDependencies does nothing; it must be overriden by descendents. The next example shows how a subclass, ProductDaoHibernateTest, implements populateDependencies. Product objects depend on Category objects, so the method reads "categories" from the dependencies and then calls a CategoryDao to create these objects. ProductDaoHibernateTest.java (excerpt)
	protected void populateDependencies() throws Exception {
		if (getDependencies() != null && getDependencies().size() > 0) {
			List objects = getDependencies().get("categories");
			List<? extends Category> categories = (List<? extends Category>)objects;
			getCategoryDao().create(categories);
		}
	}
Note that this behavior is contained in AbstractDaoTest, which is a framework class for the Case Study, but is not a member of the SpringUnit framework. Therefore, this pattern of pre-populating objects may be regarded as a pattern that can be emulated in your tests, but remains code that you will have to write in your own tests. Whether this behavior should be elevated to the SpringUnit framework is an open question.
Previous Next