Welcome to the DjaoDjin Blog!

A place to share experiences in building Software-as-a-Service.

Stubbing Java Classes

by Sebastien Mirolo on Wed, 7 Sep 2011

Many times while validating a software product, you have to substitute a few parts in order to enable automated testing. This was again the case recently when I was confronted with a java application built as a jar file. The application relied on a complex subsystem of components that needed to be stubbed out in the test runner.

A common approach is to create an interface and two implementation classes, the production one and the test runner stub, then build the jar in "release" and "debug" mode, embedding the appropriate implementation in the jar. It works but has the nasty side-effects of having two different jars for "release" and "debug". We can do better than that through the java class loading mechanism. The idea is to build a single (release) jar and put the test runner stubs earlier in the class loading path. That is how we do it. Create three source files as follow:

release/Main.java:

class Main {

        public static void main( String[] args ) {
                Override o = new Override();
                o.chachacha();
        }

}

release/Override.java:

class Override {

        public void chachacha() {
                System.out.println("Release class overriden...\n");
        }

}

release/manifest.txt:

Main-Class: Main

testRunner/Override.java:

class Override {

        public void chachacha() {
                System.out.println("TestRunner class override...\n");
        }

}

We then build a jar that contains the release classes.

$ pushd release
$ javac Main.java
$ jar cfm ../release.jar manifest.txt *.class
$ popd

Following we compile the test runner override.

$ pushd testRunner
$ javac -d .. Override.java
$ popd

Time for testing ...

$ java -cp . -jar release.jar
Release class overriden...

That did not work but the following did.

$ java -cp .:release.jar Main
TestRunner class override...