Protocol => Mocks
Data => Builders
Roadmap
• Define Maintainable Unit Test
• Create a Shared Vocabulary
• Examples
• When to Use Mocks
DefineMaintainable
Unit Test
10% of Unit Tests Break
If you really have a lot of unit tests, the amount of investment you'll have to makein maintaining those unit tests, keeping them up-to-date and keeping them passing, starts to become disproportional to the amount of benefit that you get out of them.
— Joel Spolsky
Maintainable Unit Tests
The benefits of unit tests outweigh the costs as a codebase evolves.
SharedVocabulary
Mocks
Builders
xUnit Test Patterns
Mocks
Builders
Mock Object
A mock object is a simulated object that mimics the behaviour of a real object in controlled ways.
Test Data Builder
• Builder Pattern
• build() method
• Default values
• Chainable configuration methods
Shared Vocabulary
• 4–Phase Test
• System Under Test
• Depended–On Component
• Mock Objects
• Test Data Builders
Examples
Domain Model
public void should_recognize_pediatric_patient(){ // setup Patient sut = aPatient().age(17).build();
// exercise and verify assertTrue(sut.isPediatric()); assertTrue(!sut.isAdult());}
public void should_recognize_pediatric_patient(){ // setup Patient sut = aPatient().age(17).build();
// exercise and verify assertTrue(sut.isPediatric()); assertTrue(!sut.isAdult());}
public void should_recognize_pediatric_patient(){ // setup Patient sut = aPatient().age(17).build();
// exercise and verify assertTrue(sut.isPediatric()); assertTrue(!sut.isAdult());}
aPatient().dob(april(1, 1992)).build();
Add Patient to Care Team
• Patient must be registered at the same Facility as the Care Team.
• Patient must meet the Care Team Membership Criteria (appropriate Age Category and Diagnosis).
public class CareTeamMembershipService implements ICareTeamMembershipService{ private CareTeamMembershipDao careTeamMembershipDao;
public void addMember(Patient patient, CareTeam careTeam) { if (!patient.isRegisteredAt(careTeam.getFacility())) { throw new CareTeamAdminException(); } if (!patient.meets(careTeam.getMembershipCriteria())) { throw new CareTeamAdminException(); } careTeamMembershipDao.create( patient.getId(), careTeam.getId()); }
}
private final CareTeamMembershipDao careTeamMembershipDao = context.mock(CareTeamMembershipDao.class); private final ICareTeamMembershipService sut = createCareTeamMembershipService();
public void should_permit_add_for_appropriate_care_team(){ // setup final Facility jacobi = aFacility().build(); final Patient patient = aPatient().at(jacobi).age(18) .with(Diagnosis.DIABETES).build(); final CareTeam careTeam = anAdultCareTeam().at(jacobi) .with(Diagnosis.DIABETES).build(); // verify context.checking(new Expectations() {{ one(careTeamMembershipDao).create( patient.getId(), careTeam.getId()); }}); // exercise sut.addMember(patient, careTeam);}
private final CareTeamMembershipDao careTeamMembershipDao = context.mock(CareTeamMembershipDao.class); private final ICareTeamMembershipService sut = createCareTeamMembershipService();
// verify@Test(expected=CareTeamAdminException.class)public void should_disallow_add_adult_to_pediatric_care_team(){ // setup final Facility jacobi = aFacility().build(); final Patient patient = aPatient().at(jacobi).age(18) .with(Diagnosis.DIABETES).build(); final CareTeam careTeam = aPediatricCareTeam().at(jacobi) .with(Diagnosis.DIABETES).build(); // exercise sut.addMember(patient, careTeam);}
Examples
• Test vs Production API
• Builders as shared test asset
• Mocks and Builders as Firewalls
When to Use Mocks
Mocks
Builders
Protocol
Data
Protocol => Mocks
Data => Builders
Now What?
• Read xUnit Test Patterns
• Read Nat Pryce’s Builder posts
• Distinguish Protocol vs Data
• Try using Mocks with Builders
Resources
xUnit Test Patternshttp://xunitpatterns.com/
jMockhttp://www.jmock.org/
Test Data Buildershttp://nat.truemesh.com/archives/000714.html
Credits
Obstacle Racehttp://www.flickr.com/photos/foxypar4/1004464889/
Einstein Blackboard Writing Generatorhttp://generator.kitt.net/2006/12/einstein-blackboard-writing-generator.html
Holy Grailhttp://www.flickr.com/photos/spiritual_marketplace/2207966935/