Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Efficient Test-Driven Design with Unitils : Page 3

Unitils is an open source testing framework for Java that dramatically reduces boilerplate test code. Test-driven design is a test-first methodology that uses programmatic tests as design tools. Find out how to realize the benefits of test-driven design using Unitils.


WEBINAR: On-Demand

Unleash Your DevOps Strategy by Synchronizing Application and Database Changes REGISTER >

Apply TDD to Behavioral Domain Object
Now that you understand the process, use it to implement a behavioral domain object that uses an EmployeeDao to accomplish your high-level goal of "Raise Salaries to Baseline." In the process you'll learn about how Unitils integrates EasyMock.

The IEmployeeManager interface defines the following method signatures:

public void raiseSalariesToBaseline(String title, BigDecimal baseline); public void setEmployeeDao(IEmployeeDao employeeDao);

One of the methods is simply a setter, but the other deserves some elaboration. The most important behavior of raiseSalariesToBaseline is that it actually raises salaries where appropriate. Create an executable specification in EmployeeManagerTest for this behavior by first setting up a mock IEmployeeDao:

@Mock @InjectIntoByType private IEmployeeDao employeeDao; @TestedObject private IEmployeeManager employeeManager;

Unitils automatically creates mock objects for fields annotated with @Mock, and it will use the setEmployeeDao method in your implementation to dependency inject automatically because you also included @InjectIntoByType. The @TestedObject indicates the instance of the class you're designing, and the target of all injections.

Now implement the actual behavior test, which is called raisesSalaries:

@Test public void raisesSalaries() throws DataAccessException { expect(employeeDao.findEmployeesByTitle(RAISE_TITLE)) .andReturn(newEmployeeFixture()); List<Employee> raisedEmployees = newEmployeeFixture(); raisedEmployees.get(1).setSalary(RAISE_BASELINE); raisedEmployees.get(2).setSalary(RAISE_BASELINE); employeeDao.saveEmployees(refEq(raisedEmployees.subList(1, 3), ReflectionComparatorMode.LENIENT_ORDER)); expectLastCall(); EasyMockUnitils.replay(); employeeManager.raiseSalariesToBaseline(RAISE_TITLE, RAISE_BASELINE); }

Note the use of refEq(), which is related to the Unitils ReflectionAssert class mentioned earlier. This method allows you to assert that saveEmployees gets called with a list equal to the salary-adjusted one you create in your test. Unitils uses reflection to spider all the members of each list and make sure their bean properties are equal.

It's important to note that you call newEmployeeFixture() twice. If you tried to modify the instance of your fixture returned by the mocked findEmployeesByTitle, refEq() would always succeed regardless of raiseSalariesToBaseline's behavior because EasyMock simply stores a pointer for any objects you provide in the expectations. So modifying a collection after setting an expectation with it invalidates the expectation.

For an implementation of IEmployeeManager, check out EmployeeManager in the project example.

Unitils Eases Test-Driven Design
One of the hurdles of test-driven design is the effort it takes to effectively isolate classes. Unitils goes a long way toward overcoming this issue by orchestrating packages like JUnit, DBUnit, and EasyMock, and making tests very concise and easy to write. I hope this article inspires you to try out TDD and Unitils on your next project. It's a combination that's led me to more satisfying development experiences.

Daniel Carleton has nine years of professional IT industry experience. Recently he worked as a Lead Software Engineer at a medium-sized, publicly traded company, and currently is the sole proprietor of Exaptic Solutions, a software consulting firm in Seattle, WA.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date