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