- Developing Hash Codes
- Hash Tables
- More Contracts
- The setUp Method
- Completing the Contract
- Why Bother?
The setUp Method
As I begin coding the next test, I note that I’ll want to reuse some of the same Card objects as I created for the equality tests. Time for a bit of refactoring.
Common test initialization can occur in a setUp method. The setUp method is a hook provided by JUnit that executes prior to each and every test method you define. There is also a corresponding tearDown method that you might use for common test cleanup. Mostly I use tearDown to do things like close out open database connections.
Let’s move the initialization from testEquality into this setUp method (see Listing 3).
Listing 3 Moving initialization to setUp.
public class CardTest extends TestCase { private Card card1; private Card card1copy; private Card card1copy2; private Card card2; private Card card3; protected void setUp() { card1 = new Card(Rank.king, Suit.hearts); card1copy = new Card(Rank.king, Suit.hearts); card1copy2 = new Card(Rank.king, Suit.hearts); card2 = new Card(Rank.queen, Suit.hearts); card3 = new Card(Rank.king, Suit.diamonds); } ...
Technically, you could do this common initialization in a constructor. However, follow convention and use the setUp method. It exists for that purpose.
Any tests or utility methods that work with similar instances can now use these initialized objects. Listing 4 shows the modified test for equality.
Listing 4 Modified test for equality.
public void testEquality() { assertTrue(card1.equals(card1copy)); assertFalse(card1.equals(card2)); assertFalse(card1.equals(card3)); Card card1subtype = new Card(Rank.king, Suit.hearts) {}; assertFalse(card1.equals(card1subtype)); assertReflexivity(); assertSymmetry(); assertTransitivity(); assertConsistency(); assertNullComparison(); } private void assertNullComparison() { assertFalse(card1.equals(null)); } private void assertConsistency() { assertTrue(card1.equals(card1copy)); assertFalse(card1.equals(card2)); } private void assertTransitivity() { assertTrue(card1copy.equals(card1copy2)); assertTrue(card1.equals(card1copy2)); } private void assertSymmetry() { assertTrue(card1.equals(card1copy)); assertTrue(card1copy.equals(card1)); } private void assertReflexivity() { assertTrue(card1.equals(card1)); }
Here’s the modified testHashCode that we just wrote:
public void testHashCode() { assertHashCodeConsistency(); } private void assertHashCodeConsistency() { assertEquals(card1.hashCode(), card1.hashCode()); }
Sometimes you’ll introduce new functionality, and only then recognize the duplication inherent in this code. Until you see the results in front of you, it’s often not apparent what the best tactic is for eliminating this duplication through refactoring. At other times, as in this case, you’ll find a need or desire to refactor code prior to introducing new functionality. It’s often easier that way, and in this case the refactoring necessary to stave off duplicate effort was obvious.