This site contains the documentation that is relevant to older WSO2 product versions and offerings.
For the latest WSO2 documentation, visit https://wso2.com/documentation/.

Testing Integration Scenarios

The following sections illustrate how to write an integration test class to test the use-case of integrating Google Spreadsheet Connector and Salesforce Streaming Connector based on Synapse artifacts.

Introduction

ABC is a company that maintains its invoice details in Salesforce. They need to get their invoice details in real-time and store them in a Google spreadsheet using the G oogle Spreadsheet Connector  and Salesforce Streaming Connector. They can test this scenario using the Salesforce Creating Records operation by creating an invoice via the Salesforce API. 

The following figure depicts the scenario to be tested:

 

Creating the Maven project template

Follow the steps below to create the Maven project template.

  1. Create the required Maven project template using the Maven archetype.
  2. Execute the following command to generate the sample Connector code of the Maven project:

    mvn archetype:generate -DarchetypeGroupId=org.wso2.carbon.extension.archetype -DarchetypeArtifactId=org.wso2.carbon.extension.esb.connector-archetype -DarchetypeVersion=2.0.2 -DgroupId=org.wso2.carbon.scenario -DartifactId=org.wso2.carbon.scenario.salesforcetospreadsheet -Dversion=1.0.0 -DarchetypeRepository=http://maven.wso2.org/nexus/content/repositories/wso2-public/
  3. Specify the name of the Maven project in camel case when it prompts for the name of the Connector.  (E.g., SalesforceToSpreadsheet)

    This creates the directory org.wso2.carbon.scenario.salesforcetospreadsheet in the current location of your machine.  

  4. Delete the org.wso2.carbon.scenario.salesforcetospreadsheet/src/main/ directory in the created project.

  5. Rename the org.wso2.carbon.scenario.salesforcetospreadsheet/src/test/java/org/wso2/carbon/connector/ directory as 'scenario'. (i.e. org.wso2.carbon.scenario.salesforcetospreadsheet/src/test/java/org/wso2/carbon/scenario/). 
  6. Rename the package as well.
  7. Rename the org.wso2.carbon.scenario.salesforcetospreadsheet/src/test/java/org/wso2/carbon/scenario/SalesforceToSpreadsheetConnectorIntegrationTest  java file as SalesforceToSpreadsheetScenarioIntegrationTest.

Creating the testing configurations

Follow the steps below to create the required Java files.

  1. Create the org.wso2.carbon.scenario.salesforcetospreadsheet/src/test/java/org/wso2/carbon/scenario/ScenarioIntegrationTestBase  J ava class as follows .

     This ScenarioIntegrationTestBase.java class contains all the required methods. It extends the ConnectorIntegrationTestBase interface and overrides relevant methods.

    ScenarioIntegrationTestBase.java
    package org.wso2.carbon.scenario;
    
    import org.apache.axis2.context.ConfigurationContext;
    import org.apache.commons.io.FileUtils;
    import org.json.JSONException;
    import org.json.JSONObject;
    import org.wso2.carbon.automation.api.clients.proxy.admin.ProxyServiceAdminClient;
    import org.wso2.carbon.automation.api.clients.sequences.SequenceAdminServiceClient;
    import org.wso2.carbon.automation.api.clients.utils.AuthenticateStub;
    import org.wso2.carbon.automation.core.ProductConstant;
    import org.wso2.carbon.automation.utils.axis2client.ConfigurationContextProvider;
    import org.wso2.carbon.mediation.library.stub.MediationLibraryAdminServiceStub;
    import org.wso2.carbon.mediation.library.stub.upload.MediationLibraryUploaderStub;
    import org.wso2.carbon.mediation.library.stub.upload.types.carbon.LibraryFileItem;
    import org.wso2.carbon.proxyadmin.stub.ProxyServiceAdminProxyAdminException;
    import org.wso2.carbon.sequences.stub.types.SequenceEditorException;
    import org.wso2.connector.integration.test.base.ConnectorIntegrationTestBase;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLSession;
    import javax.xml.stream.XMLStreamException;
    
    import org.testng.annotations.AfterClass;
    import org.wso2.connector.integration.test.base.RestResponse;
    
    import javax.activation.DataHandler;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.BufferedInputStream;
    import java.io.FileInputStream;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.nio.charset.Charset;
    import java.rmi.RemoteException;
    import java.util.Iterator;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Properties;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    import java.util.Map;
    
    /**
     * This class contains the all methods which are used by this scenario.
     */
    public abstract class ScenarioIntegrationTestBase extends ConnectorIntegrationTestBase {
    
        List<String> proxies = new ArrayList<String>();
        List<String> sequences = new ArrayList<String>();
    
        private static final float SLEEP_TIMER_PROGRESSION_FACTOR = 0.5f;
    
        private MediationLibraryUploaderStub mediationLibUploadStub;
        private MediationLibraryAdminServiceStub adminServiceStub;
    
        private String repoLocation;
        private String ieLocation;
    
        private ProxyServiceAdminClient proxyAdmin;
    
        private SequenceAdminServiceClient sequenceAdmin;
    
        protected Properties scenarioProperties;
    
        private String pathToProxiesDirectory;
    
        private String pathToRequestsDirectory;
    
        private String pathToSequencesDirectory;
    
        private String pathToInboundEndpointDirectory;
    
        protected String proxyUrl;
    
        protected String pathToResourcesDirectory;
    
        protected static final int MULTIPART_TYPE_RELATED = 100001;
    
        /**
         * Set up the integration test environment.
         *
         * @throws Exception
         */
    
        @Override
        protected void init() throws Exception {
    
            super.init();
    
            ConfigurationContextProvider configurationContextProvider = ConfigurationContextProvider.getInstance();
            ConfigurationContext cc = configurationContextProvider.getConfigurationContext();
    
            mediationLibUploadStub =
                    new MediationLibraryUploaderStub(cc, esbServer.getBackEndUrl() + "MediationLibraryUploader");
            AuthenticateStub.authenticateStub("admin", "admin", mediationLibUploadStub);
    
            adminServiceStub =
                    new MediationLibraryAdminServiceStub(cc, esbServer.getBackEndUrl() + "MediationLibraryAdminService");
    
            AuthenticateStub.authenticateStub("admin", "admin", adminServiceStub);
    
            if (System.getProperty("os.name").toLowerCase().contains("windows")) {
                repoLocation = System.getProperty("scenario_repo").replace("\\", "/");
            } else {
                repoLocation = System.getProperty("scenario_repo").replace("/", "/");
            }
    
            proxyAdmin = new ProxyServiceAdminClient(esbServer.getBackEndUrl(), esbServer.getSessionCookie());
            scenarioProperties = getScenarioConfigProperties("scenario");
    
            pathToProxiesDirectory = repoLocation + scenarioProperties.getProperty("proxyDirectoryRelativePath");
            pathToRequestsDirectory = repoLocation + scenarioProperties.getProperty("requestDirectoryRelativePath");
            pathToResourcesDirectory = repoLocation + scenarioProperties.getProperty("resourceDirectoryRelativePath");
            File zipFolder = new File(pathToResourcesDirectory);
            File[] listOfZIPFiles = zipFolder.listFiles();
            for (File element : listOfZIPFiles) {
                if (element.isFile()) {
                    String connectorName = element.getName();
                    if (connectorName.endsWith(".zip") || connectorName.endsWith(".ZIP")) {
                        String connectorFileName = connectorName;
                        uploadConnector(pathToResourcesDirectory, mediationLibUploadStub, connectorFileName);
    
                        // Connector file name comes with version,however mediation process only with name.
                        connectorName = connectorName.split("-")[0];
    
                        byte maxAttempts = 3;
                        int sleepTimer = 10000;
                        for (byte attemptCount = 0; attemptCount < maxAttempts; attemptCount++) {
                            log.info("Sleeping for " + sleepTimer / 1000 + " second(s) for connector to upload.");
                            Thread.sleep(sleepTimer);
                            String[] libraries = adminServiceStub.getAllLibraries();
                            if (Arrays.asList(libraries).contains("{org.wso2.carbon.connector}" + connectorName)) {
                                break;
                            } else {
                                log.info("Connector upload incomplete. Waiting...");
                                sleepTimer *= SLEEP_TIMER_PROGRESSION_FACTOR;
                            }
                        }
    
                        adminServiceStub.updateStatus("{org.wso2.carbon.connector}" + connectorName, connectorName,
                                "org.wso2.carbon.connector", "enabled");
                    }
                }
            }
            uploadProxies();
            uploadSequences();
            uploadIEs();
        }
    
        /**
         * Method to upload sequences if required from a given path.
         *
         * @throws XMLStreamException
         * @throws IOException
         * @throws SequenceEditorException
         */
        public void uploadSequences() throws IOException, SequenceEditorException, XMLStreamException {
            String sequenceDirectoryRelativePath = scenarioProperties.getProperty("sequenceDirectoryRelativePath");
            // if sequence directory relative path is available in properties, add sequences to ESB
            if (sequenceDirectoryRelativePath != null && !sequenceDirectoryRelativePath.isEmpty()) {
                pathToSequencesDirectory = repoLocation + sequenceDirectoryRelativePath;
                sequenceAdmin =
                        new SequenceAdminServiceClient(esbServer.getBackEndUrl(), esbServer.getSessionCookie());
                File sequenceFolder = new File(pathToSequencesDirectory);
                File[] listOfSequenceFiles = sequenceFolder.listFiles();
                for (File element : listOfSequenceFiles) {
                    if (element.isFile()) {
                        String fileName = element.getName();
                        if (fileName.endsWith(".xml") || fileName.endsWith(".XML")) {
                            sequences.add(fileName.replaceAll("[.][x|X][m|M][l|L]", ""));
                            sequenceAdmin.addSequence(new DataHandler(new URL("file:///" + pathToSequencesDirectory
                                    + fileName)));
                        }
                    }
                }
            }
        }
    
        /**
         * Method to upload proxies if required from a given path.
         *
         * @throws XMLStreamException
         * @throws IOException
         * @throws ProxyServiceAdminProxyAdminException
         */
        public void uploadProxies() throws IOException, XMLStreamException, ProxyServiceAdminProxyAdminException {
            File folder = new File(pathToProxiesDirectory);
            File[] listOfFiles = folder.listFiles();
            for (File element : listOfFiles) {
                if (element.isFile()) {
                    String fileName = element.getName();
                    if (fileName.endsWith(".xml") || fileName.endsWith(".XML")) {
                        proxies.add(fileName.replaceAll("[.][x|X][m|M][l|L]", ""));
                        proxyAdmin
                                .addProxyService(new DataHandler(new URL("file:///" + pathToProxiesDirectory + fileName)));
                        proxyUrl = getProxyServiceURL(fileName);
                        proxyUrl = proxyUrl.replaceAll("[.][x|X][m|M][l|L]", "");
                    }
                }
            }
        }
    
        /**
         * Method to upload inbound-endpoints if required from a given path.
         *
         * @throws InterruptedException
         */
        public void uploadIEs() throws InterruptedException {
            String inboundEndpointDirectoryRelativePath =
                    scenarioProperties.getProperty("inboundEndpointDirectoryRelativePath");
            if (inboundEndpointDirectoryRelativePath != null && !inboundEndpointDirectoryRelativePath.isEmpty()) {
                pathToInboundEndpointDirectory = repoLocation + inboundEndpointDirectoryRelativePath;
                File inboundEndpointFolder = new File(pathToInboundEndpointDirectory);
                File[] listOfIEFiles = inboundEndpointFolder.listFiles();
                ieLocation = System.getProperty("carbon.home")
                        + scenarioProperties.getProperty("inboundEndpointRelativePath");
                for (File element : listOfIEFiles) {
                    if (element.isFile()) {
                        String fileName = element.getName();
                        if (fileName.endsWith(".xml") || fileName.endsWith(".XML")) {
                            File source = new File(pathToInboundEndpointDirectory + fileName);
                            File dest = new File(ieLocation + fileName);
                            try {
                                FileUtils.copyFile(source, dest);
                                Thread.sleep(30000);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }
    
        /**
         * Clean up the ESB.
         *
         * @throws ProxyServiceAdminProxyAdminException
         * @throws SequenceEditorException
         * @throws RemoteException @
         */
        @Override
        @AfterClass(alwaysRun = true)
        public void cleanUpEsb() throws RemoteException, ProxyServiceAdminProxyAdminException {
            for (String proxyName : proxies) {
                proxyAdmin.deleteProxy(proxyName);
            }
            for (String sequenceName : sequences) {
                try {
                    sequenceAdmin.deleteSequence(sequenceName);
                } catch (SequenceEditorException e) {
                    throw new RemoteException("Unable to delete the sequence: " + e.getMessage(), e);
                }
            }
            try {
                FileUtils.cleanDirectory(new File(ieLocation));
            } catch (IOException e) {
                throw new RemoteException("Unable to delete the inbound-endpoint configuration file: " + e.getMessage(), e);
            }
        }
    
        /**
         * Upload the given connector.
         *
         * @param repoLocation
         * @param mediationLibUploadStub
         * @param strFileName
         * @throws MalformedURLException
         * @throws RemoteException
         */
        private void uploadConnector(String repoLocation, MediationLibraryUploaderStub mediationLibUploadStub,
                                     String strFileName) throws MalformedURLException, RemoteException {
    
            List<LibraryFileItem> uploadLibraryInfoList = new ArrayList<LibraryFileItem>();
            LibraryFileItem uploadedFileItem = new LibraryFileItem();
            uploadedFileItem.setDataHandler(new DataHandler(new URL("file:" + "///" + repoLocation + "/" + strFileName)));
            uploadedFileItem.setFileName(strFileName);
            uploadedFileItem.setFileType("zip");
            uploadLibraryInfoList.add(uploadedFileItem);
            LibraryFileItem[] uploadServiceTypes = new LibraryFileItem[uploadLibraryInfoList.size()];
            uploadServiceTypes = uploadLibraryInfoList.toArray(uploadServiceTypes);
            mediationLibUploadStub.uploadLibrary(uploadServiceTypes);
        }
    
        @Override
        protected RestResponse<JSONObject> sendJsonRestRequest(String endPoint, String httpMethod, Map<String, String> headersMap, String requestFileName, Map<String, String> parametersMap) throws IOException, JSONException {
            HttpURLConnection httpConnection = this.writeRequest(endPoint, httpMethod, (byte) 1, headersMap, requestFileName, parametersMap);
            String responseString = this.readResponse(httpConnection);
            RestResponse restResponse = new RestResponse();
            restResponse.setHttpStatusCode(httpConnection.getResponseCode());
            restResponse.setHeadersMap(httpConnection.getHeaderFields());
            if (responseString != null) {
                JSONObject jsonObject = null;
                if (this.isValidJSON(responseString)) {
                    jsonObject = new JSONObject(responseString);
                } else {
                    jsonObject = new JSONObject();
                    jsonObject.put("output", responseString);
                }
    
                restResponse.setBody(jsonObject);
            }
    
            return restResponse;
        }
    
        private String readResponse(HttpURLConnection con) throws IOException {
            InputStream responseStream = null;
            String responseString = null;
            if (con.getResponseCode() >= 400) {
                responseStream = con.getErrorStream();
            } else {
                responseStream = con.getInputStream();
            }
    
            if (responseStream != null) {
                StringBuilder stringBuilder = new StringBuilder();
                byte[] bytes = new byte[1024];
    
                int len;
                while ((len = responseStream.read(bytes)) != -1) {
                    stringBuilder.append(new String(bytes, 0, len));
                }
    
                if (!stringBuilder.toString().trim().isEmpty()) {
                    responseString = stringBuilder.toString();
                }
            }
    
            return responseString;
        }
    
        private HttpURLConnection writeRequest(String endPoint, String httpMethod, byte responseType, Map<String, String> headersMap, String requestFileName, Map<String, String> parametersMap) throws IOException {
            String requestData = "";
            if (requestFileName != null && !requestFileName.isEmpty()) {
                requestData = this.loadRequestFromFile(requestFileName, parametersMap);
            } else if (responseType == 1) {
                requestData = "{}";
            }
    
            OutputStream output = null;
            URL url = new URL(endPoint);
            HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
            httpConnection.setInstanceFollowRedirects(false);
            httpConnection.setRequestMethod(httpMethod);
            Iterator logOrIgnore = headersMap.keySet().iterator();
    
            while (logOrIgnore.hasNext()) {
                String key = (String) logOrIgnore.next();
                httpConnection.setRequestProperty(key, (String) headersMap.get(key));
            }
    
            if (httpMethod.equalsIgnoreCase("POST") || httpMethod.equalsIgnoreCase("PUT")) {
                httpConnection.setDoOutput(true);
    
                try {
                    output = httpConnection.getOutputStream();
                    output.write(requestData.getBytes(Charset.defaultCharset()));
                } finally {
                    if (output != null) {
                        try {
                            output.close();
                        } catch (IOException var18) {
                            this.log.error("Error while closing the connection");
                        }
                    }
    
                }
            }
    
            return httpConnection;
        }
    
        /**
         * Get scenario configuration properties.
         *
         * @param fileName Name of the file to load properties.
         * @return {@link Properties} object.
         */
        private Properties getScenarioConfigProperties(String fileName) {
    
            String scenarioConfigFile = null;
            ProductConstant.init();
            try {
                scenarioConfigFile =
                        ProductConstant.SYSTEM_TEST_SETTINGS_LOCATION + File.separator + "artifacts" + File.separator
                                + "ESB" + File.separator + "scenario" + File.separator + "config" + File.separator
                                + fileName + ".properties";
                File scenarioPropertyFile = new File(scenarioConfigFile);
                InputStream inputStream = null;
                if (scenarioPropertyFile.exists()) {
                    inputStream = new FileInputStream(scenarioPropertyFile);
                }
    
                if (inputStream != null) {
                    Properties prop = new Properties();
                    prop.load(inputStream);
                    inputStream.close();
                    return prop;
                }
    
            } catch (IOException ignored) {
                log.error("automation.properties file not found, please check your configuration");
            }
    
            return null;
        }
    
        private HttpsURLConnection writeRequestHTTPS(String endPoint, String httpMethod, byte responseType, Map<String, String> headersMap, String requestFileName, Map<String, String> parametersMap, boolean isIgnoreHostVerification) throws IOException {
            String requestData = "";
            if (requestFileName != null && !requestFileName.isEmpty()) {
                requestData = this.loadRequestFromFile(requestFileName, parametersMap);
            } else if (responseType == 1) {
                requestData = "{}";
            }
    
            OutputStream output = null;
            URL url = new URL(endPoint);
            HttpsURLConnection httpsConnection = (HttpsURLConnection) url.openConnection();
            httpsConnection.setInstanceFollowRedirects(false);
            httpsConnection.setRequestMethod(httpMethod);
            if (isIgnoreHostVerification) {
                httpsConnection.setHostnameVerifier(new HostnameVerifier() {
                    public boolean verify(String arg0, SSLSession arg1) {
                        return true;
                    }
                });
            }
    
            Iterator logOrIgnore = headersMap.keySet().iterator();
            while (logOrIgnore.hasNext()) {
                String key = (String) logOrIgnore.next();
                httpsConnection.setRequestProperty(key, (String) headersMap.get(key));
            }
    
            if (httpMethod.equalsIgnoreCase("POST") || httpMethod.equalsIgnoreCase("PUT")) {
                httpsConnection.setDoOutput(true);
    
                try {
                    output = httpsConnection.getOutputStream();
                    output.write(requestData.getBytes(Charset.defaultCharset()));
                } finally {
                    if (output != null) {
                        try {
                            output.close();
                        } catch (IOException var19) {
                            this.log.error("Error while closing the connection");
                        }
                    }
    
                }
            }
    
            return httpsConnection;
        }
    
        private String loadRequestFromFile(String requestFileName, Map<String, String> parametersMap) throws IOException {
            String requestFilePath = this.pathToRequestsDirectory + requestFileName;
            String requestData = this.getFileContent(requestFilePath);
            Properties prop = (Properties) this.scenarioProperties.clone();
            if (parametersMap != null) {
                prop.putAll(parametersMap);
            }
    
            String key;
            for (Matcher matcher = Pattern.compile("%s\\(([A-Za-z0-9]*)\\)", 32).matcher(requestData); matcher.find(); requestData = requestData.replaceAll("%s\\(" + key + "\\)", Matcher.quoteReplacement(prop.getProperty(key)))) {
                key = matcher.group(1);
            }
    
            return requestData;
        }
    
        private String getFileContent(String path) throws IOException {
            String fileContent = null;
            BufferedInputStream bfist = new BufferedInputStream(new FileInputStream(path));
    
            try {
                byte[] ioe = new byte[bfist.available()];
                bfist.read(ioe);
                fileContent = new String(ioe);
            } catch (IOException var8) {
                this.log.error("Error reading request from file.", var8);
            } finally {
                if (bfist != null) {
                    bfist.close();
                }
            }
    
            return fileContent;
        }
    
        private boolean isValidJSON(String json) {
            try {
                new JSONObject(json);
                return true;
            } catch (JSONException var3) {
                return false;
            }
        }
    }
  2. Add the test methods in the SalesforceToSpreadsheetScenarioIntegrationTest.java file by extending the ScenarioIntegrationTestBase.java class as follows.

    SalesforceToSpreadsheetScenarioIntegrationTest.java
    package org.wso2.carbon.scenario;
    
    import org.testng.Assert;
    import org.json.JSONObject;
    import org.testng.annotations.BeforeClass;
    import org.testng.annotations.Test;
    import org.wso2.carbon.integration.common.admin.client.LogViewerClient;
    import org.wso2.carbon.logging.view.stub.types.carbon.LogEvent;
    import org.wso2.connector.integration.test.base.RestResponse;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Integration test for integration scenario
     */
    public class SalesforceToSpreadsheetScenarioIntegrationTest extends ScenarioIntegrationTestBase {
    
        private Map<String, String> esbRequestHeadersMap = new HashMap<String, String>();
        private Map<String, String> apiRequestHeadersMap = new HashMap<String, String>();
        private LogViewerClient logViewer;
    
        @BeforeClass(alwaysRun = true)
        public void setEnvironment() throws Exception {
            init();
            esbRequestHeadersMap.put("Accept-Charset", "UTF-8");
            esbRequestHeadersMap.put("Content-Type", "application/json");
        }
    
        @Test(enabled = true, groups = {"wso2.esb"}, description = "Add invoice test case")
        public void testSample() throws Exception {
            RestResponse<JSONObject> esbRestResponse =
                    sendJsonRestRequest(proxyUrl, "POST", esbRequestHeadersMap, "createInvoice.json");
            Thread.sleep(10000);
            logViewer = new LogViewerClient(esbServer.getBackEndUrl(), esbServer.getSessionCookie());
            LogEvent[] logs = logViewer.getAllRemoteSystemLogs();
            boolean success = false;
            for (LogEvent element : logs) {
                if (element.getMessage().contains("Success: Successfully added the row")) {
                    success = true;
                    break;
                }
            }
            Assert.assertEquals(esbRestResponse.getHttpStatusCode(), 200);
            Assert.assertEquals(success, true, "Storing the invoice details in the spreadsheet");
        }
    }
  3. Modify the Pom.xml file as shown below.

    Pom.xml
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>org.wso2.carbon.scenario</groupId>
        <artifactId>org.wso2.carbon.scenario.salesforcetospreadsheet</artifactId>
        <version>1.0.0</version>
        <name>WSO2 Carbon - Scenario For SalesforceToSpreadsheet</name>
        <url>http://wso2.org</url>
        <properties>
            <test.framework.version>4.2.0</test.framework.version>
            <esb.version>4.9.0</esb.version>
            <carbon.kernel.version>4.4.1</carbon.kernel.version>
            <emma.version>2.1.5320</emma.version>
            <carbon.mediation.version>4.4.10</carbon.mediation.version>
            <json.version>2.0.0.wso2v1</json.version>
            <carbon.integration.framework>4.0.0</carbon.integration.framework>
            <org.testng.version>6.1.1</org.testng.version>
            <integration.base.version>1.0.1</integration.base.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.json.wso2</groupId>
                <artifactId>json</artifactId>
                <version>${json.version}</version>
            </dependency>
            <dependency>
                <groupId>org.wso2.carbon.mediation</groupId>
                <artifactId>org.wso2.carbon.connector.core</artifactId>
                <version>${carbon.mediation.version}</version>
            </dependency>
            <dependency>
                <groupId>org.wso2.carbon</groupId>
                <artifactId>org.wso2.carbon.integration.framework</artifactId>
                <version>${carbon.integration.framework}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.wso2.carbon.automation</groupId>
                <artifactId>org.wso2.carbon.automation.api</artifactId>
                <version>${test.framework.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.wso2.carbon.automation</groupId>
                <artifactId>org.wso2.carbon.automation.core</artifactId>
                <version>${test.framework.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.wso2.carbon.automation</groupId>
                <artifactId>org.wso2.carbon.automation.utils</artifactId>
                <version>${test.framework.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>emma</groupId>
                <artifactId>emma</artifactId>
                <version>${emma.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.testng</groupId>
                <artifactId>testng</artifactId>
                <version>${org.testng.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.wso2.carbon</groupId>
                <artifactId>SecVerifier</artifactId>
                <version>${carbon.kernel.version}</version>
                <type>aar</type>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.wso2.esb.integration</groupId>
                <artifactId>integration-base</artifactId>
                <version>${integration.base.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.wso2.esb</groupId>
                <artifactId>integration-test-utils</artifactId>
                <version>5.0.0-SNAPSHOT</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.0</version>
                    <configuration>
                        <source>1.5</source>
                        <target>1.5</target>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.12.4</version>
                    <inherited>false</inherited>
                    <configuration>
                        <!-- <argLine>-Xms512m -Xmx1024m -XX:MaxPermSize=128m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m -Xdebug
                           -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5006 </argLine> -->
                        <argLine>-Xms512m -Xmx1024m -XX:MaxPermSize=128m</argLine>
                        <testFailureIgnore>true</testFailureIgnore>
                        <disableXmlReport>false</disableXmlReport>
                        <parallel>false</parallel>
                        <suiteXmlFiles>
                            <suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
                        </suiteXmlFiles>
                        <systemProperties>
                            <property>
                                <name>framework.resource.location</name>
                                <value>${basedir}/src/test/resources/</value>
                                <properties>
                                    <test.framework.version>4.4.1</test.framework.version>
                                </properties>
                            </property>
                            <property>
                                <name>server.list</name>
                                <value>ESB</value>
                            </property>
                            <property>
                                <name>usedefaultlisteners</name>
                                <value>false</value>
                            </property>
                            <maven.test.haltafterfailure>false</maven.test.haltafterfailure>
                            <carbon.zip>${basedir}/repository/wso2esb-${esb.version}.zip</carbon.zip>
                            <emma.home>${basedir}/target/emma</emma.home>
                            <instr.file>${basedir}/src/test/resources/instrumentation.txt</instr.file>
                            <filters.file>${basedir}/src/test/resources/filters.txt</filters.file>
                            <emma.output>${basedir}/target/emma</emma.output>
                            <property>
                                <name>scenario_repo</name>
                                <value>${basedir}/target</value>
                            </property>
                        </systemProperties>
                        <workingDirectory>${basedir}/target</workingDirectory>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-dependency-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>copy-emma-dependencies</id>
                            <phase>compile</phase>
                            <goals>
                                <goal>copy-dependencies</goal>
                            </goals>
                            <configuration>
                                <outputDirectory>${project.build.directory}/emma</outputDirectory>
                                <includeTypes>jar</includeTypes>
                                <includeArtifactIds>emma,org.wso2.carbon.automation.core</includeArtifactIds>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
        <repositories>
            <repository>
                <id>wso2-nexus</id>
                <name>WSO2 internal Repository</name>
                <url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
                <releases>
                    <updatePolicy>never</updatePolicy>
                    <checksumPolicy>ignore</checksumPolicy>
                </releases>
            </repository>
            <repository>
                <id>wso2.releases</id>
                <name>WSO2 internal Repository</name>
                <url>http://maven.wso2.org/nexus/content/repositories/releases/</url>
                <releases>
                    <updatePolicy>never</updatePolicy>
                    <checksumPolicy>ignore</checksumPolicy>
                </releases>
            </repository>
            <repository>
                <id>wso2.snapshots</id>
                <name>Apache Snapshot Repository</name>
                <url>http://maven.wso2.org/nexus/content/repositories/snapshots/</url>
                <snapshots>
                    <updatePolicy>never</updatePolicy>
                </snapshots>
                <releases>
                    <enabled>false</enabled>
                </releases>
            </repository>
        </repositories>
        <distributionManagement>
            <repository>
                <id>nexus-releases</id>
                <name>WSO2 Release Distribution Repository</name>
                <url>http://maven.wso2.org/nexus/service/local/staging/deploy/maven2/</url>
            </repository>
            <snapshotRepository>
                <id>wso2.snapshots</id>
                <name>Apache Snapshot Repository</name>
                <url>http://maven.wso2.org/nexus/content/repositories/snapshots/</url>
            </snapshotRepository>
        </distributionManagement>
    </project>
  4. Add the correct test class name in the testng.xml file to run your test as follows.

    Testng.xml
    <test name="Sample-Scenario-Test" preserve-order="true" verbose="2">
        <packages>
            <package name="org.wso2.carbon.scenario"/>
        </packages>
    </test>

Executing the integration test

 Follow the steps below to execute the integration test.

  1. Download WSO2 ESB 4.9.0.
  2. Enable the below Axis2 configurations in the <ESB_HOME>/repository/conf/axis2/axis2.xml file.   

    Message Formatters
    <messageFormatter contentType="application/atom+xml" class="org.apache.axis2.transport.http.ApplicationXMLFormatter"/>
    <messageformatter contenttype="text/csv" class="org.apache.axis2.format.PlainTextFormatter"/>

    Message Builders
    <messageBuilder contentType="application/atom+xml" class="org.apache.axis2.builder.ApplicationXMLBuilder"/>
    <messagebuilder contenttype="text/csv" class="org.apache.axis2.format.PlainTextBuilder"/>
    <messageBuilder contentType="application/binary" class="org.wso2.carbon.relay.BinaryRelayBuilder"/>
  3. Download the inbound org.apache.synapse.salesforce.poll.class-1.0.0.jar file from store and copy it to the <ESB_HOME>/repository/components/dropins/ directory.

  4. Compress the modified ESB distribution (i.e., wso2esb-4.9.0.zip) and copy that ZIP file to the <SCENARIO_HOME>/repository/ directory.

  5. Create an access token and a refresh token from OAuth 2.0 Playground using the following URL: https://developers.google.com/oauthplayground/

    The application needs access to user data. It inquires Google for a particular scope of access. For OAuth 2.0 scope information for the Google Sheets API, see Feeds.  

  6. Set up the Google Spreadsheet environment as follows:

    • Create a Spreadsheet by logging in as a Google user with the same title you provide in step 9.
    • Create a Worksheet in that Spreadsheet with the same name you provide in step 9.
    • Add a row in the Worksheet with the following column names: Name, Id, Description, Status, CreatedDate
  7. Create the following directories inside the <SCENARIO_HOME>/src/test/resources/artifacts/ESB/config/ directory by adding the corresponding configurations.

    • Create the inboundEndpoints/scenario/ directory and add the Inbound Endpoint configuration file ( saleforceInboundEP.xml ) to it with the below content.

      saleforceInboundEP.xml file acts as a message consumer. It creates a connection to a Salesforce account and in the backend, the Salesforce streaming API receives notifications for changes to Salesforce data that match the SOQL query you define. This saleforceInboundEP consumes the Salesforce data from Salesforce streaming API and injects the data to the ESB sequence (i.e., salesforceToGSheet).


      saleforceInboundEP.xml
      <inboundEndpoint xmlns="http://ws.apache.org/ns/synapse"
                       name="SaleforceInboundEP"
                       sequence="salesforceToGSheet"
                       onError="fault"
                       class="org.wso2.carbon.inbound.salesforce.poll.SalesforceStreamData"
                       suspend="false">
          <parameters>
              <parameter name="inbound.behavior">polling</parameter>
              <parameter name="connection.salesforce.readTimeout">120000</parameter>
              <parameter name="connection.salesforce.soapApiVersion">22.0/</parameter>
              <parameter name="connection.salesforce.connectionTimeout">20000</parameter>
              <parameter name="sequential">true</parameter>
              <parameter name="connection.salesforce.waitTime">10000</parameter>
              <parameter name="connection.salesforce.packageName">cometd</parameter>
              <parameter name="coordination">true</parameter>
              <parameter name="connection.salesforce.password">xxxx</parameter>
              <parameter name="interval">10</parameter>
              <parameter name="connection.salesforce.salesforceObject">InvoStatementUpdates</parameter>
              <parameter name="connection.salesforce.userName">xxxx</parameter>
              <parameter name="connection.salesforce.loginEndpoint">https://login.salesforce.com</parameter>
              <parameter name="connection.salesforce.packageVersion">35.0</parameter>
          </parameters>
      </inboundEndpoint>
    • Create the proxies/scenario/directory and add the  Proxy Service configuration file(createInvoice.xml)to it with the below content.

      This createInvoice proxy service uses the create operation from the Salesforce connector to create a record in custom object ' Invoice_Statement__c ' in Salesforce API to test this scenario.  


      createInvoice.xml
      <proxy xmlns="http://ws.apache.org/ns/synapse"
             name="createInvoice"
             transports="https,http"
             statistics="disable"
             trace="disable"
             startOnLoad="true">
          <target>
              <inSequence>
                  <property name="username" expression="json-eval($.sfusername)"/>
                  <property name="password" expression="json-eval($.sfpassword)"/>
                  <property name="loginUrl" expression="json-eval($.loginUrl)"/>
                  <property name="sfstatus" expression="json-eval($.sfstatus)"/>
                  <property name="sfdescription" expression="json-eval($.sfdescription)"/>
                  <property name="sObjectType" expression="json-eval($.sObjectType)"/>
                  <salesforce.init>
                      <username>{$ctx:username}</username>
                      <password>{$ctx:password}</password>
                      <loginUrl>{$ctx:loginUrl}</loginUrl>
                  </salesforce.init>
                  <payloadFactory media-type="xml">
                      <format>
                          <sfdc:sObjects xmlns:sfdc="sfdc" type="$ctx:sObjectType">
                              <sfdc:sObject>
                                  <sfdc:Status__c>$ctx:sfstatus</sfdc:Status__c>
                                  <sfdc:Description__c>$ctx:sfdescription</sfdc:Description__c>
                              </sfdc:sObject>
                          </sfdc:sObjects>
                      </format>
                      <args/>
                  </payloadFactory>
                  <salesforce.create>
                      <allOrNone>0</allOrNone>
                      <allowFieldTruncate>0</allowFieldTruncate>
                      <sobjects xmlns:sfdc="sfdc">{//sfdc:sObjects}</sobjects>
                  </salesforce.create>
                  <respond/>
              </inSequence>
          </target>
          <description/>
      </proxy> 
    • Create the resources/scenario/ directory and add the Connector zip files (salesforce-connector & googlespreadsheet-connector)to it.
    • Create the restRequests/scenario/ directory and add the JSON request file to invoke the proxy service (createInvoice.json)to it with the below content.

      This request body is used by the createInvoice proxy service to make the call from the Salesforce Connector.


      createInvoiceJSON.json
      {
        "sfusername":"%s(sfusername)",
        "sfpassword":"%s(sfpassword)",
        "loginUrl":"%s(loginUrl)",
        "sfstatus":"%s(sfstatus)",
        "sfdescription":"%s(sfdescription)",
        "sObjectType":"%s(sObjectType)"
      }
    • Create the sequences/scenario/ directory and add the Sequence files (salesforceToGSheet.xml and responsesequence.xml) to it with the below content.

      The consumed data from Salesforce streaming API will be injected to this Sequence. The Sequence does the following actions:

      • Check the existence of the given Spreadsheet by its name using the getSpreadsheetByTitle operation. If that is not already created, this Sequence will break the flow and call the responsesequence sequence.

      • If the Spreadsheet is available, it checks the existence of the Worksheet in that Spreadsheet by the name of the worksheet using the getWorksheetByTitle operation. If that worksheet is not available, this sequence will add a Worksheet with the given name by using the addWorksheet operation. It will then break the flow and call the responsesequence sequence with the message, which adds a header row in the created Worksheet.

      • If both the Spreadsheet and Worksheet are available, this sequence will use the insertRows operation to insert a row with the specific fields from the consumed data.

      salesforceToGSheet.xml
      <sequence xmlns="http://ws.apache.org/ns/synapse" name="salesforceToGSheet" onError="fault">
          <property name="clientId" value="xxxx"
                    scope="default" type="STRING"/>
          <property name="clientSecret" value="xxxx" scope="default" type="STRING"/>
          <property name="refreshToken" value="xxxx" scope="default" type="STRING"/>
          <property name="accessToken" value="xxxx"
                    scope="default" type="STRING"/>
          <property name="apiUrl" value="https://spreadsheets.google.com" scope="default" type="STRING"/>
          <property name="apiVersion" value="3.0" scope="default" type="STRING"/>
          <property name="spreadsheetTitle" value="testSheet" scope="default" type="STRING"/>
          <property name="worksheetTitle" value="invoiceWorksheet" scope="default" type="STRING"/>
          <property name="rowCount" value="3" scope="default" type="STRING"/>
          <property name="colCount" value="4" scope="default" type="STRING"/>
          <property xmlns:ns="http://org.apache.synapse/xsd" name="id" expression="json-eval($.data.sobject.Id)"/>
          <property xmlns:ns="http://org.apache.synapse/xsd" name="name" expression="json-eval($.data.sobject.Name)"/>
          <property xmlns:ns="http://org.apache.synapse/xsd" name="description"
                    expression="json-eval($.data.sobject.Description__c)"/>
          <property xmlns:ns="http://org.apache.synapse/xsd" name="status" expression="json-eval($.data.sobject.Status__c)"/>
          <property xmlns:ns="http://org.apache.synapse/xsd" name="createdDate"
                    expression="json-eval($.data.sobject.CreatedDate)"/>
          <script language="js">var name = mc.getProperty('name');
              var id = mc.getProperty('id');
              var description = mc.getProperty('description');
              var createdDate = mc.getProperty('createdDate');
              var status = mc.getProperty('status');
              var fieldValues = "{";
              fieldValues += '"name":';
              var fieldValues11 = "name";
              mc.setProperty('fieldValues11', name);
              if(name != null) {
              fieldValues += '"' + name + '"';
              } else {
              fieldValues += '""';
              }
              fieldValues += ',"id":';
              if(id != null) {
              fieldValues += '"' + id + '"';
              } else {
              fieldValues += '""';
              }
              fieldValues += ',"description":';
              if(description != null) {
              fieldValues += '"' + description + '"';
              } else {
              fieldValues += '""';
              }
              fieldValues += ',"status":';
              if(status != null) {
              fieldValues += '"' + status + '"';
              } else {
              fieldValues += '""';
              }
              fieldValues += ',"createddate":';
              if(createdDate != null) {
              fieldValues += '"' + createdDate + '"';
              } else {
              fieldValues += '""';
              }
              fieldValues += "}";
              mc.setProperty('fieldValues', fieldValues);
          </script>
          <property xmlns:ns="http://org.apache.synapse/xsd" name="fieldValues" expression="$ctx:fieldValues"/>
          <googlespreadsheet.init>
              <accessToken>{$ctx:accessToken}</accessToken>
              <clientId>{$ctx:clientId}</clientId>
              <clientSecret>{$ctx:clientSecret}</clientSecret>
              <refreshToken>{$ctx:refreshToken}</refreshToken>
              <accessTokenRegistryPath>{$ctx:accessTokenRegistryPath}</accessTokenRegistryPath>
              <apiUrl>{$ctx:apiUrl}</apiUrl>
          </googlespreadsheet.init>
          <googlespreadsheet.getSpreadsheetByTitle>
              <spreadsheetTitle>{$ctx:spreadsheetTitle}</spreadsheetTitle>
          </googlespreadsheet.getSpreadsheetByTitle>
          <property xmlns:ns="http://org.apache.synapse/xsd" name="getSpreadsheetByTitleFeed" expression="json-eval($.feed)"/>
          <script language="js">var feed = mc.getProperty('getSpreadsheetByTitleFeed');
              if(feed != null) {
              var feedObject = eval("("+feed+")");
              var totalResults = feedObject["totalResults"];
              entryObject = feedObject["entry"];
              if(entryObject != null) {
              var isExists = false;
              if(totalResults == 1) {
              splitted = entryObject["id"].split("/");
              var spreadsheetKey = splitted[splitted.length-1];
              mc.setProperty('spreadsheetKey', spreadsheetKey);
              }
              if(totalResults > 1) {
              for (i = 0; i < entryObject.length; i++) {
              if(entryObject[i]["title"]["$"] == mc.getProperty("spreadsheetTitle")) {
              isExists = true;
              splitted = entryObject[i]["id"].split("/");
              var spreadsheetKey = splitted[splitted.length-1];
              mc.setProperty('spreadsheetKey', spreadsheetKey);
              break;
              }
              }
              if(!isExists) {
              totalResults = 0;
              }
              }
              }
              mc.setProperty('getSpreadsheetByTitleTotalResults', totalResults);
              }
          </script>
          <filter xmlns:ns="http://org.apache.synapse/xsd" source="$ctx:getSpreadsheetByTitleTotalResults = 0" regex="true">
              <then>
                  <property name="message" value="Error: The spreadsheet is not found"/>
                  <sequence key="responsesequence"/>
              </then>
          </filter>
          <filter xmlns:ns="http://org.apache.synapse/xsd"
                  xpath="(not($ctx:spreadsheetKey = '' or (not(string($ctx:spreadsheetKey)))))">
              <then>
                  <header name="Authorization"
                          scope="transport"
                          expression="fn:concat('Bearer ',$ctx:uri.var.accessToken)"/>
                  <googlespreadsheet.getWorksheetByTitle>
                      <key>{$ctx:spreadsheetKey}</key>
                      <worksheetTitle>{$ctx:worksheetTitle}</worksheetTitle>
                  </googlespreadsheet.getWorksheetByTitle>
                  <property name="getWorksheetByTitleFeed" expression="json-eval($.feed)"/>
                  <script language="js">var feed = mc.getProperty('getWorksheetByTitleFeed');
                      if(feed != null) {
                      var feedObject = eval("("+feed+")");
                      var totalResults = feedObject["totalResults"];
                      entryObject = feedObject["entry"];
                      if(feedObject["entry"] != null) {
                      var isExists = false;
                      if(totalResults > 1) {
                      for (i = 0; i < entryObject.length; i++) {
                      if(entryObject[i]["title"]["$"] == mc.getProperty("worksheetTitle")) {
                      isExists = true;
                      break;
                      }
                      }
                      if(!isExists) {
                      totalResults = 0;
                      }
                      }
                      }
                      mc.setProperty('getWorksheetByTitleTotalResults', totalResults);
                      }
                  </script>
                  <filter source="$ctx:getWorksheetByTitleTotalResults = 0" regex="true">
                      <then>
                          <header name="Authorization"
                                  scope="transport"
                                  expression="fn:concat('Bearer ',$ctx:uri.var.accessToken)"/>
                          <googlespreadsheet.addWorksheet>
                              <key>{$ctx:spreadsheetKey}</key>
                              <title>{$ctx:worksheetTitle}</title>
                              <rowCount>{$ctx:rowCount}</rowCount>
                              <colCount>{$ctx:colCount}</colCount>
                          </googlespreadsheet.addWorksheet>
                          <property name="addWorksheetStatusCode" expression="$axis2:HTTP_SC"/>
                          <filter source="$ctx:addWorksheetStatusCode != 201" regex="true">
                              <then>
                                  <property name="errorMessage" expression="//errors"/>
                                  <property name="message"
                                            expression="fn:concat('Error: Unable to create the worksheet (', $ctx:errorMessage,')')"/>
                                  <sequence key="responsesequence"/>
                              </then>
                              <else>
                                  <property name="message"
                                            expression="fn:concat('New spreadsheet ', $ctx:worksheetTitle,' is added. To insert data into a row, Please add a row with column names (Name, Id, Description, Status, CreatedDate)')"/>
                                  <sequence key="responsesequence"/>
                              </else>
                          </filter>
                      </then>
                      <else>
                          <header name="Authorization"
                                  scope="transport"
                                  expression="fn:concat('Bearer ',$ctx:uri.var.accessToken)"/>
                          <googlespreadsheet.listWorksheets>
                              <key>{$ctx:spreadsheetKey}</key>
                          </googlespreadsheet.listWorksheets>
                          <property name="getWorksheetByTitleFeed" expression="json-eval($.feed)"/>
                          <script language="js">
                              var feed = mc.getProperty('getWorksheetByTitleFeed');
                              if(feed != null) {
                              var feedObject = eval("("+feed+")");
                              var totalResults = feedObject["totalResults"];
                              entryObject = feedObject["entry"];
                              if(feedObject["entry"] != null) {
                              if(totalResults == 1) {
                              mc.setProperty('worksheetId', '1');
                              }
                              if(totalResults > 1) {
                              var i = 0;
                              for (i = 0; i < entryObject.length; i++) {
                              if(entryObject[i]["title"]["$"] == mc.getProperty("worksheetTitle")) {
                              var wId = ("" + (i + 1)).replace(".0", "");
                              mc.setProperty('worksheetId', wId);
                              break;
                              }
                              }
                              }
                              }
                              }
                          </script>
                          <filter xpath="(not($ctx:worksheetId = '' or (not(string($ctx:worksheetId)))))">
                              <then>
                                  <header name="Authorization"
                                          scope="transport"
                                          expression="fn:concat('Bearer ',$ctx:uri.var.accessToken)"/>
                                  <googlespreadsheet.insertRows>
                                      <key>{$ctx:spreadsheetKey}</key>
                                      <worksheetId>{$ctx:worksheetId}</worksheetId>
                                      <fieldValues>{$ctx:fieldValues}</fieldValues>
                                  </googlespreadsheet.insertRows>
                                  <property name="insertRowsStatusCode" expression="$axis2:HTTP_SC"/>
                                  <filter source="$ctx:insertRowsStatusCode != 201" regex="true">
                                      <then>
                                          <property name="errorMessage" expression="//errors"/>
                                          <property name="message"
                                                    expression="fn:concat('Error: Unable to insert the row (', $ctx:errorMessage,')')"/>
                                          <sequence key="responsesequence"/>
                                      </then>
                                      <else>
                                          <property name="message" value="Success: Successfully added the row"/>
                                          <sequence key="responsesequence"/>
                                      </else>
                                  </filter>
                              </then>
                          </filter>
                      </else>
                  </filter>
              </then>
              <else>
                  <property name="message" value="Error: The key is null"/>
                  <sequence key="responsesequence"/>
              </else>
          </filter>
      </sequence>

      responsesequence.xml
      <sequence xmlns="http://ws.apache.org/ns/synapse" name="responsesequence">
          <property name="messageType" value="application/json" scope="axis2"/>
          <payloadFactory media-type="json">
              <format>
                  {
                      "Response":{
                          "process":"enterDataToSpreadsheet",
                          "activityResponse":"$1"
                      }
                  }
              </format>
              <args>
                  <arg xmlns:ns="http://org.apache.synapse/xsd"
                       evaluator="xml"
                       expression="get-property('message')"/>
              </args>
          </payloadFactory>
  8. Rename the  <SCENARIO_HOME>/src/test/resources/artifacts/ESB/ connector/ directory as ' scenario'.
  9. Rename the  <SCENARIO_HOME>/src/test/resources/artifacts/ESB/ properties file as ' scenario.properties'.
  10. Enter valid values for the following properties in the <SCENARIO_HOME>/src/test/resources/artifacts/ESB/config/sequences/scenario/salesforceToGSheet.xml file.

    PropertyDescription
    refreshToken Use the Refresh token got in step 5.
    clientId  Use the Client ID used to generate the access token.
    clientSecret Use the Client Secret used to generate the access token.
    accessToken Use the accessToken got in step 5.
    apiVersion Use appropriate API version.
    apiUrl Use the API URL of the google spreadsheet.
    spreadsheetTitle Use the title of the spreadsheet created in step 6.
    rowCount

    Use a required number of row to a new worksheet.

    colCount  

    Use a required number of column to a new worksheet.

    worksheetTitle Use the title of worksheet created in step 6.
  11. Follow the steps below to set up the Salesforce environment.

  12. Update the following properties in the  <SCENARIO_HOME>/src/test/resources/artifacts/ESB/connector/config/googlespreadsheet file.

    • sfusername: use username of the salesforce account.
    • sfpassword: use the password of the salesforce account.
    • loginUrl: use login URL of the salesforce account.
    • sfstatus: use the status of the invoice e.g: Open, Closed, Negotiating and Pending
    • sfdescription: use description about that invoice entry
    • sObjectType: use the type of the sObject created in step 10.
  13.   Check if the following relative paths are stated properly in the properties file.  

    • proxyDirectoryRelativePath=/../src/test/resources/artifacts/ESB/config/proxies/scenario/

    • requestDirectoryRelativePath=/../src/test/resources/artifacts/ESB/config/restRequests/scenario/

    • resourceDirectoryRelativePath=/../src/test/resources/artifacts/ESB/config/resources/scenario/

    • sequenceDirectoryRelativePath=/../src/test/resources/artifacts/ESB/config/sequences/scenario/

    • inboundEndpointDirectoryRelativePath=/../src/test/resources/artifacts/ESB/config/inboundEndpoints/scenario/

    • inboundEndpointRelativePath=/repository/deployment/server/synapse-configs/default/inbound-endpoints/

  14. Navigate to the <SCENARIO_HOME>/  directory and execute the following command to execute your test classes and generate the reports in  target/surefire-reports/ directory: mvn clean install 

    For the sample, go to Github.