When you write service based applications, services seldom 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 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 times.
Fabric3 provides service mocking using the mock implementation using Easymock, which we will cover in this section.
Adding Mock Functionality to Hello World
In this section we will have a look at how service mocking can be used in the hello world example. Let us say each time the sayHello method is called, the component implementation will log the call using a monitor service, whose service contract is shown below:
public interface HelloWorldMonitor {
void onSayHello(String name);
}
The code for the service implementation class has now 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="urn:fabric3.org"
name="HelloWorldTestComposite"
autowire="true">
<component name="HelloWorldTest">
<f3:junit class="HelloWorldITest"/>
<reference name="helloWorld" target="HelloWorldComposite"/>
<reference name="monitor" target="MockComponent/HelloWorldMonitor"/>
</component>
<component name="HelloWorldComposite">
<implementation.composite name="helloWorldComposite" scdlResource="helloWorld.composite" />
<reference name="monitor" target="MockComponent/HelloWorldMonitor"/>
</component>
<component name="MockComponent">
<f3:implementation.mock>
HelloWorldMonitor
</f3:implementation.mock>
</component>
</composite>
The implementation type, 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 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 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() {
control.reset();
monitor.onSayHello("Fred");
control.replay();
assertEquals("Hello, Fred", helloWorld.sayHello("Fred"));
control.verify();
}
}
Before you can run the test, you need to modify the POM to add dependency on Easymock and also enable the Fabric3 Easymock extension,
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>helloworld</groupId>
<artifactId>helloworld</artifactId>
<packaging>jar</packaging>
<version>0.1</version>
<name>Hello World Test</name>
<dependencies>
<dependency>
<groupId>org.codehaus.fabric3.spec</groupId>
<artifactId>sca-api-r1.0</artifactId>
<version>0.2.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>2.2</version>
</dependency>
</dependencies>
<build>
<defaultGoal>verify</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
<compilerArgument>-g</compilerArgument>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/*ITest.java</exclude>
</excludes>
</configuration>
</plugin>
<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>
<executions>
<execution>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
0 Comments