Defining Stub classes by reusing Test Data

Introduction

In early march of 2011 I received an email with thanks for doing DDTUnit in the first place.
A guy from Sweden, Sven Blix, introduced an idea to implement stubbing interfaces by reusing DDT test data he could use for the implementation object of the interface as well

I found this aspect of reuse in test data quite appealing, so we started out in cooperation to integrate his ideas directly in DDTUnit.
In the following paragraphs you will find more details on the basic ideas and the implementation details we chose.

The basic idea

Most of the time the design starts out with the definition of an interface which can be used by other teams and service users.
To start with the development of dependent services and clients we usually provide a mock for the service to come. After some time of development the actual service is ready for integration test. An extra specification test is required to verify the correct behavior.

What if the mock object and the test suite for the real implementation provide the same behavior verification?

An Example

We start with a simple service with one method:

public interface VOGeneratorInterface {

  public ComplexVO generateComplexVO(String text, SimpleVO simpleVO);
}

The stubbing implementation uses the DDTDataRepository of DDTUnit to provide expected behavior on special input.
public class StubbedVOGenerator implements VOGeneratorInterface {

  public ComplexVO generateComplexVO(String text, SimpleVO simpleVO) {
    System.out.println("A call with parameter:\n\n\"" + simpleVO + "\"");

    String classId = RealVOGeneratorTest.class.getSimpleName();

    String resourceName = ResourceNameFactory.getInstance().getName(
        ClassAnalyser.classPackage(RealVOGeneratorTest.class), classId);

    TestClusterDataSet clusterDataSet = DDTDataRepository.getInstance()
        .get(resourceName, classId);


    final String testId = "testGenerateComplexVO";
    final String textId = "objectText";
    final String simpleVOId = "objectSimpleVO";
    final String assertId = "expectedComplexVO";

    SearchParameters params = new SearchParameters();
    params.addParameter(textId, simpleVO);
    params.addParameter(simpleVOId, simpleVO);
    SearchCriteria searchCriteria = new SearchCriteria(testId, params, assertId);

    ComplexVO complexVO = (ComplexVO) DDTDataRepository.find(clusterDataSet, searchCriteria);

    System.out.println("\n is stubbed with \n\n \"" + complexVO + "\"\n");

    return complexVO;
  }
}
        

An example of the behavior specification could look like this

Use object part of test as input parameters of method and return objects provided by assert part of test definition.

The same test data definition can be used to verify the implementation class of the interface.

public class RealVOGeneratorTest extends DDTTestCase {

  @Override
  protected void initContext() {
    String classId = RealVOGeneratorTest.class.getSimpleName();
    initTestData(classId);
  }

  public void testGenerateComplexVO() {
    String text = (String) getObject("objectText");
    SimpleVO simpleVO = (SimpleVO) getObject("objectSimpleVO");
    VOGeneratorInterface voGenerator = new RealVOGenerator();
    ComplexVO actualComplexVO = voGenerator.generateComplexVO(text, simpleVO);
    assertObject("expectedComplexVO", actualComplexVO);
  }

}
        

Open Issues

What is missing?

  • The structure of the stubbing class can be optimized
  • The xml structure should be more expressive
sf logo