Mocking Services with EasyMock

When you write service based applications, services rarely function in isolation. Services may depend on other services for implementing a cohesive piece of functionality. When testing a service implementation, it is often desirable to mock its dependencies, particularly if those dependencies are services external to the current application.

Fabric3 provides service mocking using a special component implementation type based on EasyMock (http://www/easymock.org).

Adding Mock Functionality to Hello World

Returning to the previous hello world example, let's change the implementation to log the call using a monitor service:

public interface HelloWorldMonitor {
   void onHello(String name);
}

The code for the service implementation class is changed to incorporate the call to the above service:

public class HelloWorldImpl implements HelloWorld {

    @Reference 
    protected HelloWorldMonitor monitor;

    public String sayHello(String name) {
        monitor.onHello(name);
        return "Hello " + name;
    }
}

The HelloWorldMonitor can be mocked in the test composite as follows:

<composite name="TestComposite" targetNamespace="urn:fabric3.org" ...>
           
   <component name="HelloWorldTest">
        <f3:junit class="...HelloWorldITest"{color}/>
        <reference name="helloWorld" target="HelloWorldComponent"/>
    </component>
  
    <component name={color:#378d00}"MockComponent"{color}>
        <f3:implementation.mock>
            HelloWorldMonitor
        </f3:implementation.mock>
    </component>
  
    <include name="HelloWorldComposite/>

</composite>

In the above, implementation.mock takes a list of comma-separated fully-qualified names of interfaces that need to be mocked.

Once this is setup, the JUnit test component can be modified to use the Easymock API to verify the right number of calls are made to the monitor service by the HelloWorldImpl component.

public class HelloWorldITest extends TestCase {

    @Reference 
    protected HelloWorld helloWorld;

    @Reference 
    protected IMocksControl control;

    @Reference 
    protected HelloWorldMonitor monitor;

    public void testSayHello() {

        control.reset();
        monitor.onSayHello("Foo");
        control.replay();
        assertEquals("Hello Foo", helloWorld.sayHello("Fred"));
        control.verify();

    }
}

Before the test is run, be sure to add Easymock as a project dependency and the Fabric3 mock extension to the runtime configuration:

<project>
    <modelVersion>4.0.0</modelVersion>

    <dependencies>
       ...

        <dependency>
            <groupId>org.easymock</groupId>
            <artifactId>easymock</artifactId>
            <version>2.2</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.fabric3</groupId>
                <artifactId>fabric3-itest-plugin</artifactId>
                <configuration>
                    <extensions>
                        <dependency>
                            <groupId>org.fabric3</groupId>
                            <artifactId>fabric3-mock</artifactId>
                            <version>RELEASE</version>
                        </dependency>
                    </extensions>
                    <shared>
                        <dependency>
                            <groupId>org.easymock</groupId>
                            <artifactId>easymock</artifactId>
                            <version>2.2</version>
                        </dependency>
                    </shared>
                </configuration>
        </plugins>
    </build>
</project>