![Page 1: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/1.jpg)
Unit Testing Case Study: How Ohio Mutual Insurance Group Got Started
Nick Watts
Senior Programmer/Analyst for OMIG
Technical Editor of NFJS, The Magazine
![Page 2: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/2.jpg)
NFJS, The Magazine
• Extension of the No Fluff Just Stuff (NFJS) travelling symposium.
• Only NFJS speakers write articles for the magazine.
• Delivered as PDF and ePub file downloads.
• www.nofluffjuststuff.com/home/magazine_subscribe
• @nfjsmag on Twitter.
© Copyright, Ohio Mutual Insurance Group 2
![Page 3: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/3.jpg)
Agenda
• Testing Education
• Getting Started in Unit Testing
• Mock Objects
© Copyright, Ohio Mutual Insurance Group 3
![Page 4: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/4.jpg)
Learn
• Over 2 – 3 years we read articles about, attended user group meetings about, took a class as part of a Masters degree about and attended conference sessions on testing.
• Bewilderment is an appropriate response for the first 6 – 12 months (or so).
© Copyright, Ohio Mutual Insurance Group 4
![Page 5: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/5.jpg)
Learn
• The article that finally made unit testing make sense to me:
– Evolutionary architecture and emergent design: Test-driven design, Part 1 by Neal Ford.
• http://www.ibm.com/developerworks/java/library/j-eaed2/
© Copyright, Ohio Mutual Insurance Group 5
![Page 6: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/6.jpg)
Practice
• Over the 2 – 3 year learning period we also practiced writing unit tests.
• We started with the simplest possible JUnit tests we could find to do.– Neal Ford asks the question, "What is the simplest
thing for which I can write a test?"
• Over time we were able to improve and write tests for increasingly trickier situations.
• Trying overly-complex tests was a common first misstep.
© Copyright, Ohio Mutual Insurance Group 6
![Page 7: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/7.jpg)
Understand
• It was absolutely necessary to understand the code in order to begin testing it.
• The newest member of the team has been on for over 2 years.
© Copyright, Ohio Mutual Insurance Group 7
![Page 8: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/8.jpg)
Learn, Practice and Understand
• This was a v e r y l o n g process!
• Do not expect to get immediately satisfying results.
• Though some people present it so, building a significant set of unit tests on an existing code base is not easy or quick.
© Copyright, Ohio Mutual Insurance Group 8
![Page 9: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/9.jpg)
Reflect
• This all seems so obvious, why am I telling you?– It helps to hear that someone else went through
the same experience.
– Speakers and authors glaze over real details, such as “this is REALLY hard to do in REAL life”, to remain brief.
© Copyright, Ohio Mutual Insurance Group 9
![Page 10: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/10.jpg)
The Case Study
• Real code from a live production system that has been in place for over five years.
• Brief analysis of some of the core business classes in the system.
• Brief description of major hurdles to writing tests against the code.
• Analysis of some methods for testing the code before refactoring it.
© Copyright, Ohio Mutual Insurance Group 10
![Page 11: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/11.jpg)
Why A Case Study?
• Unit testing examples are often trite and too far off from reality.
• I believe you either are, were, or will be as confused as my team was when we began writing unit tests.
• I hope you’ll learn more by seeing real code than by seeing contrived examples.
© Copyright, Ohio Mutual Insurance Group 11
![Page 12: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/12.jpg)
yDoc UML Diagram: Typical Example
© Copyright, Ohio Mutual Insurance Group 12
![Page 13: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/13.jpg)
yDoc UML Diagram: More Realistic
© Copyright, Ohio Mutual Insurance Group 13
![Page 14: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/14.jpg)
What is This Mess?
• Core business domain package of a legacy JEE system (e-Quip’d™) atop a legacy COBOL policy management system (POINT IN).– Roughly mirrors the logical view of a “policy” in
POINT IN.
– e-Quip’d™ was not built with unit testing in mind.
© Copyright, Ohio Mutual Insurance Group 14
![Page 15: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/15.jpg)
What’s the Problem? Or, excuses for not unit testing
• “I’m not sure where to start because I can’t understand the code.”– Complexity
• “I don’t want to write a test that uses static data because it’s not a good test.”– Validity of Simple Tests
© Copyright, Ohio Mutual Insurance Group 15
![Page 16: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/16.jpg)
What’s the Problem? Or, excuses for not unit testing
• “It’s too much of a hassle to write a test because of all the dependencies.”– Unruly Coupling
• “I’m not supposed to write unit tests for methods that connect to a database.”– Unexpected Database Connections
© Copyright, Ohio Mutual Insurance Group 16
![Page 17: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/17.jpg)
Complexity
• This is “the ugly truth” in real code. Complexity abounds (both accidental and intentional).
• The complexity made the task of testing seem hopeless at first. We were unable to decide where to start because there is no clear entry point.
© Copyright, Ohio Mutual Insurance Group 17
![Page 18: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/18.jpg)
How We Worked with the Complexity
• Used Old fashioned “elbow grease”.– Understood the business domain and the systems
that support it.
– Studied the code.
– Communicated with others who work on the system.
• A visualization is very helpful.– yDoc is an inexpensive way to start visualizing
your code in class-sized chunks.
© Copyright, Ohio Mutual Insurance Group 18
![Page 19: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/19.jpg)
Basic Policy Class Hierarchy
© Copyright, Ohio Mutual Insurance Group 19
![Page 20: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/20.jpg)
More Realistic Policy Class Hierarchy
© Copyright, Ohio Mutual Insurance Group 20
![Page 21: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/21.jpg)
How We Worked with the Complexity
Started simple: Chose the simplest classes we could find. Usually POJOs and Beans with little or no business logic.
© Copyright, Ohio Mutual Insurance Group 21
![Page 22: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/22.jpg)
Example of a Simple Test: OMIGSSNumber Class
public class OMIGSSNumberTest {
public void test_default_constructor() {
OMIGSSNumber ssn = new OMIGSSNumber();
assertNotNull(ssn);
assertNotNull(ssn.getSsNo());
assertEquals(ssn.getSsNo(), "");
}
}
© Copyright, Ohio Mutual Insurance Group 22
![Page 23: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/23.jpg)
Validity of Simple Tests
• At first, we also stumbled just writing some of the “simplest” tests.
• Putting static data into tests felt unnatural.
• Tests with static data seemed invalid.
© Copyright, Ohio Mutual Insurance Group 23
![Page 24: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/24.jpg)
Example of Simple Tests with Static Data
public void test_GetModifiedJulianDate() {
OMIGDate od = new OMIGDate(2008, 8, 16);
assertEquals(od.getModifiedJulianDate(), 54694);
}
© Copyright, Ohio Mutual Insurance Group 24
![Page 25: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/25.jpg)
How We Worked with the Validity of Simple Tests
More practice and learning. It just took time to realize that it was acceptable to build static test cases that didn’t test all scenarios.
© Copyright, Ohio Mutual Insurance Group 25
![Page 26: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/26.jpg)
Example of Simple Tests with Static Data
public void test_trans_history_full_constructor() {TransactionHistoryRow row = new
TransactionHistoryRow("01“,"21“,"05“,"CPQ“,"1234567“,"00“,"0888000“,"0888z“,"00“,3);
assertEquals("01", row.getLco());assertEquals("21", row.getMco());assertEquals("05", row.getPco());assertEquals("CPQ", row.getSymbol());assertEquals("1234567", row.getNumber());assertEquals("00", row.getMod());assertEquals("0888000", row.getAgencyId());assertEquals("0888z", row.getUserId());assertEquals("00", row.getProducerCode());assertEquals(3, row.getActivityCode());
}
© Copyright, Ohio Mutual Insurance Group 26
![Page 27: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/27.jpg)
Unruly Coupling
• Instantiating an object is unnecessarily complex because of coupling.– E.g. the BasicContract class constructor requires a
PolicyKey reference be passed in, which requires that a ProductKey reference be passed in, which requires five Strings for its constructor.
– BasicContract is itself used in hundreds of classes.
© Copyright, Ohio Mutual Insurance Group 27
![Page 28: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/28.jpg)
Unexpected Database Connections
• Testing a method that connects to a database can be troublesome, but can be circumvented.
• A class that connects to a database in a constructor is more than troublesome to test (i.e. you can’t just ignore a constructor).– E.g. PolicyBase
© Copyright, Ohio Mutual Insurance Group 28
![Page 29: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/29.jpg)
How We Worked Around Unruly Coupling in Unit Tests
You could repeatedly instantiate all of the objects necessary to create the one you’re really interested in testing.
This code isn’t un-testable, it’s just a nuisance.
© Copyright, Ohio Mutual Insurance Group 29
![Page 30: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/30.jpg)
How We Worked Around Unruly Coupling in Unit Tests
public void test_basic_contract() {
ProductKey prodKey =
new ProductKey("01", "20", "05", "OH", "CPP");
PolicyKey polKey = new PolicyKey(prodKey);
BasicContract bc = new BasicContract(polKey);
assertNotNull(bc);
}
What about testing classes that require a BasicContract reference to instantiate?
© Copyright, Ohio Mutual Insurance Group 30
![Page 31: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/31.jpg)
How We Worked Around Unruly Coupling in Unit Tests
• Our solution was to just mock the troublesome classes and ignore the setup of the object.– You eventually want to refactor and remove the
unruly coupling. So start by pretending its not there by mocking.
© Copyright, Ohio Mutual Insurance Group 32
![Page 32: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/32.jpg)
How We Worked Around Unruly Coupling in Unit Tests
public void test_basic_contract_best() {
BasicContract bc = mock(BasicContract.class);
assertNotNull(bc);
}
This is best because it is succinct, doesn’t require custom test code and the intent is very clear.
© Copyright, Ohio Mutual Insurance Group 33
![Page 33: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/33.jpg)
“Mock it and forget it”
• We took the easiest path by just mocking the class we wanted to test.
• Most of the object’s state is not needed, so we don’t set it up.– Notice the deep knowledge of the classes involved
in this statement.
– Caution! Carefully consider an object’s internal state.
© Copyright, Ohio Mutual Insurance Group 34
![Page 34: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/34.jpg)
Mock Objects
• “mocks do not implement any logic: They are empty shells that provide methods to let the tests control the behavior of all the business methods of the faked class. “– JUnit in Action, 2nd ed.
• Read about mock objects in JUnit in Action by Vincent Massol and Ted Husted and JUnit in Action, 2nd ed. by Tachiev et. al.
© Copyright, Ohio Mutual Insurance Group 35
![Page 35: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/35.jpg)
Enter Mockito
• Mockito is a mock object framework.– Gives you an object that looks like the real object,
but may or may not, at you discretion, act like the real object.
– Has a very English-like syntax.
– Very good at working with “legacy” code.
– www.mockito.org
© Copyright, Ohio Mutual Insurance Group 36
![Page 36: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/36.jpg)
Example of Common Mockito Usage in OMIG Code
We want to test this method in PolicyBase:
public void putOnHold() throws Exception {
getBasicContract().setEndType("HLD");
storeAppInfo();
}
© Copyright, Ohio Mutual Insurance Group 37
![Page 37: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/37.jpg)
An Attempt at Testing putOnHold() Without Mocking
public void test_put_on_hold__sans_mocking() throws Exception {
ProductKey prodKey =
new ProductKey("01", "20", "06", "RI", "CPP");
Policy policy = new Policy(prodKey);
assertTrue(StringUtils.isBlank(
policy.getBasicContract().getEndType()));
policy.putOnHold();
assertTrue(policy.isOnHold());
} © Copyright, Ohio Mutual Insurance Group 38
![Page 38: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/38.jpg)
Basic Policy Class Hierarchy
© Copyright, Ohio Mutual Insurance Group 39
![Page 39: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/39.jpg)
An Attempt at Testing putOnHold() Without Mocking
© Copyright, Ohio Mutual Insurance Group 40
Without mocking, the test won’t run because it connects to a database.
![Page 40: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/40.jpg)
Example of Common Mockito Usage in OMIG Code
The previous method is hard to test because of unruly coupling and the storeAppInfo() method, which connects to a database. The solution…
public void test_put_on_hold() throws Exception {Policy policy = mock(Policy.class);when(policy.getBasicContract()).
thenCallRealMethod();when(policy.isOnHold()).thenCallRealMethod();doCallRealMethod().when(policy).putOnHold();…
}
© Copyright, Ohio Mutual Insurance Group 41
![Page 41: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/41.jpg)
Summary
• Took our time with unit testing as it was a big commitment.
• Started with small, easy unit tests.
• Increased our abilities with learning and practice – over time.
• Used mock objects to solve our biggest problems.
© Copyright, Ohio Mutual Insurance Group 42
![Page 42: Unit Testing Case Study for COJUG - 05.11.2010](https://reader034.vdocuments.net/reader034/viewer/2022052618/554d2acfb4c905c5208b50ca/html5/thumbnails/42.jpg)
Contacting Me
• [email protected] – work email
• @nfjsmag – Twitter (for NFJS, The Magazine)
• Slides at: http://www.slideshare.net/thewonggei/unit-testing-case-study-cojug05112010
© Copyright, Ohio Mutual Insurance Group 43