Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

When you write service based applications, services seldom rarely function in isolation. Services may depend on other services for implementing a cohesive piece of functionality. And, of course, dependency from the implementation of one service to another would be through well-defined service contracts. In the previous chapter we saw these dependencies in the SCA world are expressed using references.
When you unit test testing a service implementation, you may or may not have the implementation of other services it depend on. For example, the implementation of the dependency may come from the same composite, in which case, when you unit test the composite all the dependencies would have been catered for. In other scenarios, implementations of the dependencies may come from extrenal composites, in which case, the references would have been promoted. In such scenarios, you may want to mock those references and verify the behaviour of the composites in terms of the references being called expected number of timesit is often desirable to mock its dependencies, particularly if those dependencies are services external to the current application.

Fabric3 provides service mocking using the mock implementation using Easymock, which we will cover in this section.

...

a special component implementation type based on EasyMock (http://www/easymock.org).

Adding Mock Functionality to Hello World

In this section we will have a look at how service mocking can be used in the Returning to the previous hello world example. Let us say each time the sayHello method is called, the component implementation will , let's change the implementation to log the call using a monitor service, whose service contract is shown below:

Code Block
java
java

public interface HelloWorldMonitor {

...


   void onHello(String name);

...


}

The code for the service implementation class has now is changed to incorporate the call to the above service:
import org.osoa.sca.annotations.Reference;
public class HelloWorldImpl implements HelloWorld {
@Reference protected HelloWorldMonitor monitor;
public String sayHello(String name) {
monitor.onSayHello(name);
return "Hello, " + name;
}
}
Let us say the monitor service comes from a different composite, so our service composite promotes the reference as shown below, so that it can be provided in the context in which the composite will be used as a component.
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" name="HelloWorldComposite" targetNamespace="urn:helloWorld">
<service name="helloWorldService" promote="HelloWorldComponent"/>
<reference name="monitor" promote="HelloWorldComponent/monitor"/>
<component name="HelloWorldComponent">
<implementation.java class="HelloWorldImpl"/>
</component>
</composite>
Now, when we test the above composite the monitor reference will have to be provided. However, in our integration test, rather than using a real implementation of the monitor service, we use a mock implementation using Fabric3 mock support.
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
xmlns:f3

Code Block
java
java

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:

Code Block
xml
xml

<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 like junit belongs to the Fabric3 namespace and is an implementation provided by Fabric3 to support mocking service references in integration tests. The implementation takes a list of token comma-separated fully-qualified names of interfaces that need to be mocked. Note: When autowire is switched on you dont need to explictly specify all the references and target them. This would make the composite less verbose.
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
xmlns:f3="urn:fabric3.org"
name="HelloWorldTestComposite"
autowire="true">
<component name="HelloWorldTest">
<f3:junit class="HelloWorldITest"/>
</component>
<component name="HelloWorldComposite">
<implementation.composite name="helloWorldComposite" scdlResource="helloWorld.composite" />

</component>
<component name="MockComponent">
<f3:implementation.mock>
HelloWorldMonitor
</f3:implementation.mock>
</component>
</composite>
Now in the test code, we can 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 being tested. import org.osoa.sca.annotations.Reference;
import junit.framework.TestCase;
import org.easymock.EasyMock;
import org.easymock.IMocksControl;
public class HelloWorldITest extends TestCase {
@Reference protected HelloWorld helloWorld;
@Reference protected IMocksControl control;
@Reference protected HelloWorldMonitor monitor;
public void testSayHello() {

Code Block
java
java


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:

Code Block
xml
xml

<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.codehaus.fabric3</groupId>
                <artifactId>fabric3-itest-plugin</artifactId>
                <configuration>
                    <extensions>
                        <dependency>
                            <groupId>org.codehaus.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>