6.6 Generating Mock Objects with MockMaker

6.6.1 Problem

You want to automatically generate a mock object from any Java interface.

6.6.2 Solution

Use MockMaker, available from http://www.mockmaker.org.

6.6.3 Discussion

Writing mock objects by hand is tedious, and relying on a framework like Mock Objects is troublesome because it might not provide mock implementations for all of the interfaces you need to test against. The MockMaker project allows you to automatically generate new mock objects from any existing Java interface.

Using MockMaker is simple. Just include the MockMaker JAR files in your CLASSPATH and invoke the tool as follows:

java mockmaker.MockMaker  <interfaceName>

The generated source code is then echoed to the console. Example 6-11 shows the output from typing the following command:

java mockmaker.MockMaker javax.swing.event.TableModelListener
Example 6-11. Generated mock object
import mockmaker.ReturnValues;
import com.mockobjects.*;
import javax.swing.event.TableModelListener;
import javax.swing.event.TableModelEvent;
public class MockTableModelListener implements TableModelListener{
   private ExpectationCounter myTableChangedCalls = new ExpectationCounter("javax.swing.
event.TableModelListener TableChangedCalls");
   private ExpectationList myTableChangedParameter0Values = new ExpectationList("javax.
swing.event.TableModelListener TableChangedParameter0Values");
   public void setExpectedTableChangedCalls(int calls){
      myTableChangedCalls.setExpected(calls);
   }
   public void addExpectedTableChangedValues(TableModelEvent arg0){
      myTableChangedParameter0Values.addExpected(arg0);
   }
   public void tableChanged(TableModelEvent arg0){
      myTableChangedCalls.inc(  );
      myTableChangedParameter0Values.addActual(arg0);
   }
   public void verify(  ){
      myTableChangedCalls.verify(  );
      myTableChangedParameter0Values.verify(  );
   }
}

The generated code relies on code found in the Mock Objects framework for keeping track of expectations, such as the expected events or number of times a method was called. You use this class almost exactly like you would use the hand-coded mock object, as shown in Example 6-5 (although the method names are slightly different).

Here is how you can run MockMaker from an Ant buildfile:

<path id="classpath.mockmaker">
  <pathelement path="${dir.build}"/>
  <pathelement location="${env.MOCKMAKER_HOME}/mockmaker.jar"/>
  <pathelement location="${env.MOCKMAKER_HOME}/mmmockobjects.jar"/>
  <pathelement location="${env.MOCKMAKER_HOME}"/>
</path>

...

<target name="generateMockObjects" depends="prepare">
  <java fork="true" classname="mockmaker.MockMaker"
        output="${dir.generatedSrc}/MockTableModelListener.java">
    <classpath refid="classpath.mockmaker"/>
    <arg line="javax.swing.event.TableModelListener"/>
  </java>
</target>

6.6.4 See Also

Recipe 6.2 and Recipe 6.3 show how to hand-code mock objects that look similar to the code generated by MockMaker. The Mock Objects web site, http://www.mockobjects.com, lists URLs for several other mock object generation tools, including Easy Mock, Mock Creator, and Mock Doclet.