A Brute Force JUnit Test
We begin by writing a typical JUnit test of the constructor
for CompositeDate. January 1 and December 31 are obvious
boundary cases.
For each test, we introduce input values for year, month and day,
and expected values again for each of those.
We call the constructor with with inputs
and check that the fields of the constructed object
match our expectations.
package org.springunit.examples.constructor.junit.v1;
public class CompositeDateConstructorTest extends TestCase {
public void testJan01() throws Exception {
int day = 1;
int month = 1;
int year = 2006;
int expectedDay = 1;
int expectedMonth = 1;
int expectedYear = 2006;
CompositeDate subject = new CompositeDate(year, month, day);
assertTrue(expectedMonth == subject.getMonth());
assertTrue(expectedDay == subject.getDay());
assertTrue(expectedYear == subject.getYear());
}
public void testDec31() throws Exception {
int day = 31;
int month = 12;
int year = 2006;
int expectedDay = 31;
int expectedMonth = 12;
int expectedYear = 2006;
CompositeDate subject = new CompositeDate(year, month, day);
assertTrue(expectedMonth == subject.getMonth());
assertTrue(expectedDay == subject.getDay());
assertTrue(expectedYear == subject.getYear());
}
}
Next we add tests for valid leap days. The first checks for the
sort that happens every four years; the second checks those
that occur once every four hundred. (Three of every four centuries
are not leap years, an exception to the rule that every fourth
year is a leap year.)
public void testFeb29Leap2004() throws Exception {
int day = 29;
int month = 2;
int year = 2004;
int expectedDay = 29;
int expectedMonth = 2;
int expectedYear = 2004;
CompositeDate subject = new CompositeDate(year, month, day);
assertTrue(expectedMonth == subject.getMonth());
assertTrue(expectedDay == subject.getDay());
assertTrue(expectedYear == subject.getYear());
}
public void testFeb29Leap2000() throws Exception {
int day = 29;
int month = 2;
int year = 2000;
int expectedDay = 29;
int expectedMonth = 2;
int expectedYear = 2000;
CompositeDate subject = new CompositeDate(year, month, day);
assertTrue(expectedMonth == subject.getMonth());
assertTrue(expectedDay == subject.getDay());
assertTrue(expectedYear == subject.getYear());
}
Four months have 30 days; the test for April is representative.
For the date April 31, an InvalidDateException should be thrown:
that is the expected result.
For this kind of test, where the throwing of an exception
is the expected behavior, this is a common pattern.
A try-catch block surrounds the call to the method(s) being
tested, and a test failure is declared if calling the
method fails to throw an exception.
public void testApr31() throws Exception {
int day = 31;
int month = 4;
int year = 2006;
try {
CompositeDate subject = new CompositeDate(year, month, day);
fail("Exception not thrown");
}
catch (InvalidDateException ex) {
}
}
February requires similar tests for the 30th and 31st (not shown here).
But February 29 requires two separate test cases:
when a year is not evenly divisible by 4 and a century is
not evenly divisible by 400.
public void testFeb29NoLeap() throws Exception {
int day = 29;
int month = 2;
int year = 2003;
try {
CompositeDate subject = new CompositeDate(year, month, day);
fail("Exception not thrown");
}
catch (InvalidDateException ex) {
}
}
public void testFeb29NoLeap1900() throws Exception {
int day = 29;
int month = 2;
int year = 1900;
try {
CompositeDate subject = new CompositeDate(year, month, day);
fail("Exception not thrown");
}
catch (InvalidDateException ex) {
}
}
At this point, we have thoroughly tested the constructor
for the class under test, CompositeDate.
Under most circumstances on many projects, this is good enough.
It should be obvious by now, though, that there is considerable
code repetition throughout this TestCase.
If we're serious about our unit testing and need
to keep these tests maintained, we may want to have a second look.
We'll start to do something about that by
Removing Duplicate Code.