Approaching

This was my first get in touch with Axis2. After some struggling with the dependencies I got it running. I’ve setup a WebService, the WeatherService. This Service requires a WeatherServiceSupplier to retrieve a Weather object. Pretty simple and straight forward. Now, I want to test the remote part of the WebService and use mocks for external stuff which is the WeatherServiceSupplier. After the service was created and registered in the services.xml we can step into the test phase.

Test phase vs. Real World

In a real world application, you use perhaps Spring, J2EE, or other stuff. For sure, you don’t want to start up the whole stack just to test a WebService. To decouple your WebService from the stuff, which is not in scope, you’ve to define a set of classes which are under test. Axis2 requires a service class name and creates instances of the service itself, but you don’t want to change the class name for the test, just to make it testable. Therefore you have to tell Axis2 somehow to use special classes/instances for your test. These objects are prepared with mocks and must be integrated with Axis2. Luckily Axis2 allows you to specify a ServiceObjectSupplier parameter. The specified class has to implement the ServiceObjectSupplier interface and is used to retrieve instances of a service. In case you do not use ServiceObjectSuppliers in your production code, you can proceed with the examples. If you use ServiceObjectSuppliers within your service descriptors, you have to rethink about splitting them into production and test, to be able to inject custom objects.

I used my test class, AxisServerAndClientTest as ServiceObjectSupplier. I manage all the dependencies in there: The Axis2-Server itself, the system under test (WeatherService) and the mocks. Most of the code is in order to setup the Axis2-Server or client.

The used service is a very simple Pojo accessing an interface to retrieve the weather. In real world this interface would be implemented by a real service.


public class WeatherService
{
    private WeatherServiceSupplier supplier;

    public Weather getWeather(String location)
    {
        return supplier.getWeather(location);
    }
}

public interface WeatherServiceSupplier
{
    Weather getWeather(String location);
}

This snippet shows a part of the Test. You can find the full file here.

@RunWith(MockitoJUnitRunner.class)
public class AxisServerAndClientTest implements ServiceObjectSupplier
{
    @InjectMocks
    private static WeatherService sut = new WeatherService();

    @Mock
    private static WeatherServiceSupplier supplier;

    private static int port = RemoteUtil.findFreePort();
    private static AxisServer server = new AxisServer();

    @BeforeClass
    // ...setup server...

    @AfterClass
    // ...stop server...
    
    @Test
    public void getWeather() throws Exception
    {
        // Setup Mock
        when(supplier.getWeather(anyString())).thenAnswer(new Answer<Weather>()
        {
            @Override
            public Weather answer(InvocationOnMock invocation) throws Throwable
            {
                return new Weather(42, "It'll be sunny in " + invocation.getArguments()[0], false, 0);
            }
        });

        // Axis 2 Client stuff
        RPCServiceClient serviceClient = new RPCServiceClient();
        Options options = serviceClient.getOptions();
        
        String endpoint = "http://localhost:" + port +
                              "/axis2/services/WeatherService";

        EndpointReference targetEPR = new EndpointReference(endpoint);
        options.setTo(targetEPR);

        // Getting the weather
        QName opGetWeather = new QName("http://service.pojo.sample", 
                                                         "getWeather");
        Object[] opGetWeatherArgs = new Object[] { "Weinheim" };
        Class[] returnTypes = new Class[] { Weather.class };

        Object[] response = serviceClient.invokeBlocking(opGetWeather, 
                                         opGetWeatherArgs, returnTypes);
        Weather weather = (Weather) response[0];

        // Assertions
        assertEquals("It'll be sunny in Weinheim", weather.getForecast());
    }

    /**
     * Callback-Method to retrieve the Service
     *
     * @param theService
     * @return Service-Instance using Mocks
     */
    public Object getServiceObject(AxisService theService)
    {
        if (theService.getName().equals("WeatherService"))
        {
            return sut;
        }
        return null;
    }
}

You can find the code on GitHub, http://github.com/mp911de/webservice-test-axis. The project uses Maven for build.