The problem with the code from the previous post is "All those private methods are untestable." To resolve this we refactor again -- ending up with 8 files containing 50 lines of production code and approximately 180 lines of test code, like so:
public class EventListener{ private EventComparer eventComparer = new EventComparer(); private DuplicateEventHandler duplicateEventHandler; private Event previousEvent = null; public EventListener( DuplicateEventHandler duplicateEventHandler){ this.duplicateEventHandler = duplicateEventHandler; } public void onEvent(Event currentEvent) { bool previousEventIsValid = (previousEvent != null); if(previousEventIsValid && eventComparer.isSameEvent( previousEvent, currentEvent)) { duplicateEventHandler.handleSameEvent(currentEvent); } previousEvent = currentEvent.cloneEvent(); } }; public class EventComparer{ private EventLocationComparer eventLocationComparer = new EventLocationComparer(); private EventTimeComparer eventTimeComparer = new EventTimeComparer(); public bool sameEvent( Event currentEvent, Event previousEvent){ return eventLocationComparer.isSameLocation( currentEvent, prevousEvent) && eventTimeComparer.isSameTime( currentEvent, previousEvent); } }; public class LocationComparer{ static final int X_LIMIT = 200; static final int Y_LIMIT = 200; public bool isSameLocation( Event currentEvent, Event previousEvent){ return (isSamePoint( currentEvent.getX(), previousEvent.getX(), X_LIMIT) && (isSamePoint( currentEvent.getY(), previousEvent.getY(), Y_LIMIT); } public bool isSamePoint( int current, int previous, int tolerance){ return math.abs(current - previous) < tolerance; } }; public class TimeComparer{ static final long TIME_LIMIT = 500L; public bool isSameTime( Event currentEvent, Event previousEvent){ return currentEvent.getTime() - previousEvent.getTime() < TIME_LIMIT; } }; public class EventListenerTest{ private EventListener testObject; private Event event1 = new Event(parameter); @Mock private DuplicateEventHandler duplicateEventHandler; @Before public void setup(){ testObject = new EventListener(duplicateEventHandler); testObject.onEvent(event1); } @Test public void thisIsATypicalTest(){ Event event2 = new Event(various parameters to test boundary conditions); testObject.onEvent(event2); verify(duplicateEventHandler).handleSameEvent(event2); // or depending on the parameters to event2... verify(duplicateEventHandler, never()). handleSameEvent(event2); } }; public class EventComparerTest{ private EventComparer testObject; private Event event1 = new Event(parameter); @Before public void setup(){ testObject = new EventComparer(); } @Test public void thisIsATypicalTest(){ Event event2 = new Event(various parameters to test boundary conditions); bool testResult = testObject.sameEvent(test1, test2); assertTrue(testResult); } }; public class EventLocationComparerTest{ private EventLocationComparer testObject; private Event event1 = new Event(parameter); @Before public void setup(){ testObject = new EventLocationComparer(); } @Test public void thisIsATypicalTest(){ Event event2 = new Event(various parameters to test boundary conditions); bool testResult = testObject.isSameLocation( test1, test2); assertTrue(testResult); } @Test public void thisIsAnotherTypicalTest(){ Random random = new Random(); int testValue1 = random.next(); int testLimit = random.next(); int testValue2 = testValue1 plus or minus testLimit plus or minus one. bool testResult = testObject.isSamePoint( testValue1, testValue2, testLimit); assertTrue(testResult); } }; public class EventTimeComparerTest{ private EventTimeComparer testObject; @Before public void setup(){ testObject = new EventTimeComparer(); } @Test public void thisIsATypicalTest(){ Event event2 = new Event(various parameters to test boundary conditions); bool testResult = testObject.isSameTime(test1, test2); assertTrue(testResult); } };It may be a bit long, but hey, it's testable. (..or not. See the next post.)
No comments:
Post a Comment