One of the more time-consuming and tedious chores in writing unit tests that involve mocks, is setting up the test data for mock expectations. For example, let's say we are testing service class code like this:
List<Student> advisees = advisorDao.getAdvisees(); |
Our unit test would use a mock version of advisorDao, and we would tell the mock framework to expect a call to getAdvisees() and for this method call to return a list of Student objects. We would need to instantiate a number of Student objects and add them all to a List. Perhaps our test also requires us to peek inside the Student objects and examine the enrollment profile or other embedded objects. We would be required to instantiate all of these objects and set them inside our Student objects. This takes a lot of time and is very tedious.
The intent of the test data builder framework is to make "helper" classes available that will do a lot of this data setup for the programmer. These will be simple factory classes, instantiating commonly used objects like Student, and populating them with values that make sense.
Design considerations:
Here is an example of one of these builder classes - it's called CoreDataFactory and is intended to provide common data used across many apps. The interfaces for creating Student objects is like this:
public Student buildStudent(); public Student buildStudent(String termCode); |
There are just two variations- the first (no-arg) method will return a Student object with all basic data fields filled in. It will also populate enrollment profile information for the current term (based on a simple current date calculation). The second method, taking term code as an argument builds a similar Student object, but it uses the supplied term code for any term-specific data like enrollment profile.
So a unit test needing Student objects for test data now only needs to do this for each student object:
CoreDataFactory builder = new CoreDataFactory(); Student student = builder.buildStudent(); |
and no longer needs to do this:
PersonName personName = new PersonName("David", "Lee", "Roth"); String kerbName = nameGenerator.getName(); String emailAddress = kerbName + "@mit.edu"; Random random = new Random(); int pidm = 12212871; // should be int between 100,000 and 199,999 int mitId = 90002312; // should be int between 900,000,000 and 990,000,000 Student student = new Student(String.valueOf(pidm), String.valueOf(mitId), kerbName, personName, emailAddress); Calendar now = Calendar.getInstance(); student.setCitizenship(new Citizenship("US", "United States")); student.setEthnicity(new StudentEthnicity()); Calendar birthDate = Calendar.getInstance(); birthDate.set(Calendar.YEAR, birthDate.get(Calendar.YEAR) - 20); // Born 20 years ago student.setBirthDate(birthDate.getTime()); student.setDeceased(false); student.setGender(Gender.FEMALE); student.setStudentHolds(new ArrayList<StudentHold>()); student.setVersion(1l); student.setCreateBy("testuser"); student.setCreateDate(now.getTime()); student.setModifyBy("testuser2"); student.setModifyDate(now.getTime()); // Enrollment profile: Set enrollProfiles = new HashSet(); // ... more code that builds enrollment profile objects... student.setStudentEnrollProfiles(enrollProfiles); |