Test everything! – Lessons Learned from SOA-fying a Monolith

Another lesson we learned while making our legacy application ready for a service-oriented architecture, is this:

Test everything.

Test everything

When I started out writing Flow services in webMethods Integration Server (IS), there was no (nice) way of automatically testing them. Although we were told multiple times by consultants, that there would be a test framework for IS, we never got the actual code. So, I had to develop a test framework myself, simply to be sure that everything still worked as before after a deployment of IS.

The result of my development effort are two small Java frameworks:

I wanted to be able to test IS services (Flow, Java, etc.) with the established tool we already used in our projects: JUnit. However, Integration Server’s Java interface relies on IData, the internal representation of IS’s pipeline. And working with it can get pretty annoying, because it’s nothing more than a big hash table with its own API. So you would have to deconstruct your Java objects into the structure of IData every time you call a service and compose them back together when you get the results, only to be able to call an assertion on it.

ao-idata-converter

My solution for this problem is a project called ao-idata-converter. It takes any Plain Old Java Object (POJO) and converts it to IData with a bit of reflection magic. You can even use beans with Getters and Setters and map attribute names to different fields in the pipeline. So, with ao-idata-converter you can get rid of all the converting from and to IData in your code.

IData convertedObject =
    new ObjectConverter().convertToIData("address", addressObject);

ao-integrationserver

The next problem I faced, was the need to use lots of boilerplate code to be able to call an IS service. If you generate a Java client for a given IS service, the resulting class contains all the setup, authentication, input etc. you need to call the service. However, it’s not reusable and you’ll end up with lots of duplication if you want to call multiple services (which would be the default behaviour, I guess).

Therefore, I abstracted all the needed boilerplate code into a separate framework, ao-integrationserver, that provides an easy API for calling IS services on different endpoints with authentication and input/output parameters represented by simple POJOs. If you follow a certain naming convention for your Java packages and classes, you’ll be able to call an IS service by creating a single class with only a few lines of code. So, adding a new service to your Java library takes only a few minutes at most.

public class max extends Service<max.Input, max.Output>
{
    public static class Input extends ServiceInput
    {
        public String[] numList;
    }

    public static class Output extends ServiceOutput
    {
        public String maxValue;
    }
}

Our test suite

Below you can see a screenshot of our IS test suite in Eclipse. The test suite automatically runs on our Jenkins build server every time we deploy IS and we can point it to any stage (development, test, production) within a matter of seconds to make sure that all services still work as expected.

Screenshot of our test suite for Integration Server

If you would like to know more about the two frameworks or our deployment pipeline, feel free to contact me any time. If you would like to participate in the development of the frameworks, I would also love to hear from you (e.g. via a Pull Request).

Leave a Comment

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax