September 22, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Working With Design Patterns: Factory Method

  • August 28, 2008
  • By Jeff Langr
  • Send Email »
  • More Articles »

Inheritance hierarchies containing an abstract base class present a small challenge for unit testing: How do common superclass methods get tested? Because you can't instantiate an abstract class, should you create an extension of it solely for purposes of testing? Or, do you re-test each of the public inherited methods for each subclass? Maybe it's sufficient simply to exercise the set of subclasses.

I can rule out the last choice: Public behavior needs to be explicitly tested, so it is not sufficient to test only against the subclass public methods. The first option, creating a test-only subclass of the target (the class being tested), is theoretically not a bad idea. It demonstrates that the public behavior works with stubbed implementations for abstract methods. In practice, though, it's probably best if the common public behavior works in conjunction with every derived class. No question then remains as to whether the public behavior works in context with the concrete class code.

That leaves you with the second choice—re-test each public method in each subclass. The downside is that this could generate a lot of redundant test code. Consider listing 1, which shows the test for a FloatColumn class. FloatColumn is an abstraction of an SQL column used for an object-to-relational mapping tool. Each such SQL column class requires a name upon construction, and must return that name when asked (via a getName method call). The common code in FloatColumn and other types like StringColumn and DateColumn can obviously be pushed into a base class, perhaps AbstractColumn. Listing 2 shows the relevant portions of both FloatColumn and AbstractColumn.

Listing 1: FloatColumnTest.

package persistence.types;

import static org.junit.Assert.*;
import org.junit.*;

public class FloatColumnTest {
   protected Column column;
   static final String NAME = "name";

   @Before
   public void setUp() {
      column = new FloatColumn("name");
   }

   @Test
   public void create() {
      assertEquals("name", column.getName());
   }

   @Test
   public void isEqualToColumnWithSameName() {
      assertTrue(column.equals(createColumn(NAME)));
   }

   @Test
   public void isUnequalToColumnWithDifferentName() {
      assertFalse(column.equals(createColumn(NAME + "x")));
   }

   @Test
   public void isUnequalToNull() {
      assertFalse(column.equals(null));
   }

   @Test
   public void isUnequalToObjectOfDifferentType() {
      assertFalse(column.equals("oranges"));
   }

   @Test
   public void isUnequalToObjectOfSubtype() {
      Column subInstance = new FloatColumn(NAME) {
      };
      assertFalse(column.equals(subInstance));
   }

   @Test
   public void hashIsEqualForEqualObjects() {
      assertEquals(column.hashCode(),
                   createColumn(NAME).hashCode());
   }

   private Column createColumn(String name) {
      return new FloatColumn(name);
   }

   // ... other specific FloatColumn tests ...
}

Listing 2: The Column class implementations.

// AbstractColumn.java
package persistence.types;

abstract public class AbstractColumn implements Column {
   private String name;

   public AbstractColumn(String name) {
      this.name = name;
   }

   public String getName() {
      return name;
   }

   public boolean equals(Object object) {
      if (this == object) return true;
      if (object == null || !(object instanceof Column) ||
         object.getClass() != this.getClass())
         return false;
      Column that = (Column)object;
      return this.getName().equals(that.getName());
   }

   public int hashCode() {
      return getName().hashCode();
   }
   // ...
}

// FloatColumn.java
package persistence.types;

public class FloatColumn extends AbstractColumn {
   public FloatColumn(String name) {
      super(name);
   }
   // ...
}




Page 1 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel