paint-brush
Creating API-Helpers Using the Citrus Integration Frameworkby@taacoder
119 reads

Creating API-Helpers Using the Citrus Integration Framework

by Alexey TaranenkoJune 17th, 2022
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

In this article, I want to show you how you can create and configure API helpers using Java and the Citrus Integration Framework. Further helpers can already be used in a test project to send a request to the desired interface and, accordingly, receive a response with further validation of the obtained data. We will look at helpers for such system interfaces as: REST, SOAP and WebSocket services. I think they are the most popular and we encounter them more often than others in testing. In general, this is all for helpers now.
featured image - Creating API-Helpers Using the Citrus Integration Framework
Alexey Taranenko HackerNoon profile picture

In this article, I want to show you how you can create and configure API helpers using Java and the Citrus Integration Framework. Further helpers can already be used in a test project to send a request to the desired interface and, accordingly, receive a response with further validation of the obtained data.

We will look at helpers for such system interfaces as: REST, SOAP and WebSocket services. I think they are the most popular and we encounter them more often than others in testing.

Below is a call to the REST service:

    @Test()
    @CitrusTest
    public void getTestActions() {
        this.context = citrus.createTestContext();

        http(httpActionBuilder -> httpActionBuilder
        .client("httpHelperClient")
        .send()
        .get("users"));

        http(httpActionBuilder -> httpActionBuilder
        .client("httpHelperClient")
        .receive()
        .response(HttpStatus.OK)
        .messageType(MessageType.JSON)
        .payload(getJsonData(), "objectMapper"));
    }

I also show you how to configure the client "bean" and "objectMapper" in the citrus-context.xml file. This client can then be used in the helper to send the request, and the "objectMapper" can be used for serialization and deserialization.

    <!--HTTP-Helper-->
    <citrus-http:client
            id="httpHelperClient"
            request-url="${url}"
            content-type="application/json"
            timeout="30000"/>

    <bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper">
        <property name="serializationInclusion" value="NON_NULL"/>
    </bean>

Below is a call to the SOAP service:

    @Test()
    @CitrusTest
    public void getTestActions() {
        this.context = citrus.createTestContext();

        PojoToXML<Class<NumberToDollars>> convRequest = new PojoToXML<>();
        PojoToXML<Class<NumberToDollarsResponse>> convResponse = new PojoToXML<>();


        soap(soapActionBuilder -> soapActionBuilder
                        .client("soapHelperClient")
                        .send()
                        .payload(convRequest.convert(NumberToDollars.class, getNumberToDollarsRequest(), "http://www.dataaccess.com/webservicesserver/", "NumberToDollars" ))
        );

        soap(soapActionBuilder -> soapActionBuilder
                        .client("soapHelperClient")
                        .receive()
                        .xsdSchemaRepository("schemaRepositoryService")
                        .payload(convResponse.convert(NumberToDollarsResponse.class, getNumberToDollarsResponse(), "http://www.dataaccess.com/webservicesserver/", "NumberToDollarsResponse"))
        );
    }

In this code i use my custom Marshaler named PojoToXML. Code below:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.namespace.QName;
import java.io.IOException;
import java.io.OutputStream;

public class PojoToXML<T> {
    public T generic;

    public String convert(T requestClass, Object requestData, String namespaseURI, String localPart) { //namespaseURI=http://oms.rt.ru/ , localPart=submitOrderRequest
        generic = requestClass;
        String s = null;

        try {
            JAXBContext jaxbContext = JAXBContext.newInstance((Class) requestClass);
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

            // To format XML
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            JAXBElement<T> jaxbElement =
                    new JAXBElement<T>(new QName(namespaseURI, localPart),
                            (Class) requestClass,
                            (T) requestData);

            OutputStream output = new OutputStream() {
                private StringBuilder string = new StringBuilder();
                @Override
                public void write(int b) throws IOException {
                    this.string.append((char) b );
                }

                public String toString(){
                    return this.string.toString();
                }
            };
            jaxbMarshaller.marshal(jaxbElement, output);
            s = String.valueOf(output);

        } catch (JAXBException e) {
            e.printStackTrace();
        }
        return s;
    }
}

I also show how to configure the client "bean" and additional settings for working with xml in the citrus-context.xml file.

<!--SOAP-Helper-->
    <citrus-ws:client
            id="soapHelperClient"
            request-url="${urlSOAP}"
            timeout="30000"/>

    <!--For SOAP 1.1-->
    <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
        <property name="soapVersion">
            <util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_11"/>
        </property>
    </bean>

    <citrus:schema-repository id="schemaRepositoryService">
        <citrus:schemas>
            <citrus:schema id="DATAACCESS" location="classpath:wsdl/numberconversion.wsdl" />
        </citrus:schemas>
    </citrus:schema-repository>

Below is a call to the WebSocket service:

    @Test()
    @CitrusTest
    public void getTestActionsWSS(){
        this.context = citrus.createTestContext();

        send(action -> action
                .endpoint("wssHelperClient")
                .fork(true)
        );

        receive(action -> action
                .endpoint("wssHelperClient")
                .messageType(MessageType.JSON)
                .payload(getJsonDataResponseWSS(), "objectMapper")
        );
    }

I also show you how to configure the client "bean" in the citrus-context.xml file and you should add an "objectMapper" in case of interaction by JSON messages.

    <!--WSS-Helper-->
    <citrus-websocket:client
            id="wssHelperClient"
            url="${urlWSS}"
            timeout="30000"/>

    <bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper">
        <property name="serializationInclusion" value="NON_NULL"/>
    </bean>

To summarize, in each case we create two "actions", one action to send a request and the second to receive a response and then validate the data. In general, this is all for helpers now. I hope my examples help you.